// ==UserScript== // @name Bugzilla Script // @namespace xiwenge // @version 0.68.0 // @author xiwenge // @description 美化增强 Bugzilla 页面 // @icon https://www.bugzilla.org/assets/img/logo-header.svg // @match *://192.168.1.31/bugzilla* // @match *://192.168.1.31/bugzilla/show_bug.cgi* // @match *://192.168.1.31/bugzilla/buglist.cgi* // @match *://192.168.1.31/bugzilla/query.cgi* // @match *://192.168.1.31/bugzilla/summarize_time.cgi* // @match *://192.168.1.31/bugzilla/attachment.cgi* // @match *://192.168.1.31/bugzilla/enter_bug.cgi* // @match *://192.168.1.31/bugzilla/describecomponents.cgi* // @match *://192.168.1.31/bugzilla/show_activity.cgi* // @match *://192.168.1.31/bugzilla/process_bug.cgi* // @grant GM_addStyle // @grant GM_setClipboard // @grant GM_xmlhttpRequest // @run-at document-end // ==/UserScript== (function () { 'use strict'; const d=new Set;const importCSS = async e=>{d.has(e)||(d.add(e),(t=>{typeof GM_addStyle=="function"?GM_addStyle(t):(document.head||document.documentElement).appendChild(document.createElement("style")).append(t);})(e));}; 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, typeof key !== "symbol" ? key + "" : key, value); const indexLess = 'body{margin:0!important;padding:13px!important;--primaryColor: #18A058;--primaryColorHover: #15904e;--textGrayColor: #b1b1b1}::-webkit-scrollbar{width:12px}::-webkit-scrollbar-track{background:#f1f1f1;border-radius:12px}::-webkit-scrollbar-thumb{background:#b9bbbd;border-radius:12px}::-webkit-scrollbar-thumb:hover{cursor:pointer;background:#a6a9ac;transform:scale(1.2)}::-webkit-scrollbar:horizontal{height:12px}::-webkit-scrollbar-track:horizontal{background:#f1f1f1;border-radius:12px}::-webkit-scrollbar-thumb:horizontal{background:#b9bbbd;border-radius:12px}::-webkit-scrollbar-thumb:hover:horizontal{cursor:pointer;background:#a6a9ac;transform:scale(1.2)}#header .links .form form,#footer .links .form form{display:inline-flex!important;align-items:center}#header{position:sticky;top:0;z-index:100}#header #title{display:block;width:270px}.monaco-editor{width:100%!important;height:100%!important}.navigation{padding:2px;display:flex;align-items:center}.bz_query_buttons[valign=middle]{display:flex}.bz_query_buttons[valign=middle] form:not(:last-child){margin-right:10px}.custom-button{display:inline-flex;align-items:center!important;width:fit-content!important;height:28px;background-color:var(--primaryColor);border-radius:4px!important;color:#fff;top:0;right:0;bottom:0;left:0;opacity:1;transition-duration:.3s;transition-property:box-shadow,opacity,color,border;padding:4px 12px!important;font-weight:400;font-size:12px;margin:0 5px;box-sizing:border-box;text-decoration:none;line-height:18px;border:1px solid transparent;-webkit-user-select:none;user-select:none}.custom-button:hover{height:28px;cursor:pointer;color:#fff!important;background-color:var(--primaryColorHover)}.custom-button:visited{color:#fff}.plain-button{background:#fff!important;color:#757575!important;border:1px solid #cccccc!important;text-decoration:none!important}.plain-button:hover{height:28px;color:var(--primaryColor)!important;border:1px solid var(--primaryColor)!important}.text-button{background:transparent!important;color:#4a4a4a!important;border:none!important;text-decoration:none!important}.text-button:hover{cursor:pointer;color:#4a4a4a!important;box-shadow:none!important}.disabled-button{cursor:not-allowed!important;border-color:#d9d9d9!important;color:#00000040!important;background:#0000000a!important;box-shadow:none!important;pointer-events:none!important}.disabled-button:hover{cursor:not-allowed!important;border-color:#d9d9d9!important;color:#00000040!important;box-shadow:none!important}.field_label{vertical-align:middle!important}select{height:28px;border-radius:4px;padding:4px;border-color:#d9d9d9;box-sizing:border-box}select:hover{cursor:pointer}select:focus-visible{outline:#d9d9d9}#available_columns,#selected_columns{height:300px;display:block;margin-right:4px}#assigned_to_list_vue_app,#assigned_to_list_vue_app .n-base-selection-label{height:28px}input:not([class=n-input__input-el])[type=checkbox]:hover{cursor:pointer}input:not([class=n-input__input-el])[type=radio]:hover{cursor:pointer}input:not([class=n-input__input-el]):not([type=radio]):not([type=checkbox]):not([type=range]):not([type=color]):not([type=hidden]):not([type=reset]):not([type=file]){height:28px!important;border-radius:4px;padding:0 6px;outline:0px solid transparent;border:1px solid #d9d9d9;box-sizing:border-box}textarea{border-radius:4px;padding:4px;outline:0px solid transparent;border:1px solid #d9d9d9}#status{margin-bottom:unset;align-items:center;display:flex;margin-top:3px}.knob-buttons:has(input[id=commit]){margin-top:4px}#bug_status{margin:0 6px}.bz_section_spacer{display:none}#bz_assignee_input{width:543px}#set_default_assignee_label,#set_default_assignee{display:none}.bz_assignee_td{display:flex;align-items:center;width:598px}#bz_show_bug_column_1 tr th{min-height:34px!important}#bz_show_bug_column_1 tr:has(th[id=field_label_tag]){transform:translateY(2px)}#bz_show_bug_column_1 tr:has(th[id=field_label_dependson]){transform:translateY(4px)}#bz_show_bug_column_1 tr:has(th[id=field_label_blocked]){transform:translateY(6px)}#bz_show_bug_column_1 tr:has(td[id=show_dependency_tree_or_graph]){display:none}#bz_show_bug_column_1 tr td{min-height:34px!important}#bz_show_bug_column_2 .field_label{vertical-align:middle!important;max-width:200px}#bz_show_bug_column_2 table tr td{max-width:100%}#cf_newfeatureid{width:100%}.global-message{width:fit-content;height:fit-content;padding:8px 24px;box-sizing:border-box;display:inline-flex;align-items:center;position:fixed;left:50%;transform:translate(-50%,-50%);z-index:99999999;background-color:#fff;border-radius:4px;transition:opacity .5s ease-in-out,top .5s ease-in-out;animation:message-fadein .5s ease-in-out forwards;box-shadow:0 0 6px #0003}.global-message_text{margin-left:8px;font-size:14px}@keyframes message-fadein{0%{opacity:.5;top:10px}to{opacity:1;top:30px}}@keyframes loading{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.global-dialog{height:fit-content;max-width:100vw;max-height:100vh;z-index:9999;position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);background-color:#fff;border-radius:4px}.global-dialog .control-btn:hover{cursor:pointer}.global-dialog .control-btn:not(:last-child){margin-right:8px}.global-dialog .close-btn:hover{filter:drop-shadow(0px 0px 2px #ff5953)}.global-dialog .exit-full-screen-btn:hover{filter:drop-shadow(0px 0px 2px #fabe33)}.global-dialog .full-screen-btn:hover{filter:drop-shadow(0px 0px 2px #53c32b)}.global-dialog-header{padding:6px 12px;background-color:#f5f5f5;border-radius:4px 4px 0 0}.global-dialog-footer{padding:6px 12px;background-color:#f5f5f5;border-radius:0 0 4px 4px;display:flex;justify-content:flex-end;box-sizing:border-box}.global-dialog-body{max-width:100%;max-height:calc(100% - 68px);height:100%;padding:12px 24px;overflow-y:auto;overflow-x:auto;box-sizing:border-box}.global-dialog-mask{width:100vw;height:100vh;position:fixed;top:0;left:0;background-color:#00000080}.global-dialog-mask-transparent{background-color:transparent}.global-loading{width:100%;height:100%;position:relative}.global-loading:after{content:"";width:20px;height:20px;border:2px solid var(--primaryColor);border-left:2px solid transparent;border-radius:50%;position:absolute;top:calc(50% - 10px);left:calc(50% - 10px);transform:translate(-50%,-50%);animation:loading 1.5s infinite linear;background-color:transparent}.self-rotate{animation:loading 1.5s infinite linear}.attachment-container{width:100%;height:100%;overflow-y:auto;overflow-x:auto}.flex{display:flex}.flex-wrap{flex-wrap:wrap}.flex-center{display:flex;justify-content:center;align-items:center}.flex-align-center{display:flex;align-items:center}.flex-justify-center{display:flex;justify-content:center}.flex-justify-space-between{display:flex;justify-content:space-between}.flex-justify-end{display:flex;justify-content:flex-end}.show{display:block}.show-inline-block{display:inline-block}.hide{display:none}.cursor-pointer:hover{cursor:pointer}.text-underline{text-decoration:underline}.font-size-16px{font-size:16px}.font-bold{font-weight:700}.margin-right-8px{margin-right:8px}.margin-left-8px{margin-left:8px}.margin-bottom-8px{margin-bottom:8px}.margin-top-8px{margin-top:8px}.link-title{font-weight:700;transition:all .3s ease-in-out}.link-title:hover{color:var(--primaryColor)!important;text-decoration:unset!important}.separator{margin:0 6px 0 4px;color:#ccc}.links .form a[title="Quicksearch Help"]{margin-left:6px}#attachment_table,#attachment_table td{border:1px solid #d9d9d9}#attachment_table tr td[valign=top]:nth-child(2):has(a){display:flex;justify-content:center;align-items:center}#summary_field.search_field_row input{padding-bottom:unset!important;vertical-align:middle}#short_desc{padding-bottom:unset!important}#summary_field.search_field_row select{padding-bottom:4px;vertical-align:middle}.bz_quip{display:block;color:var(--textGrayColor);font-weight:700;font-size:12px;font-style:italic;margin-top:8px;font-family:黑体}.bz_query_timestamp{color:var(--textGrayColor);font-style:normal;font-size:14px;display:inline-block;font-family:黑体}.n-base-selection__border,.n-base-selection__state-border{display:none}.n-checkbox .n-checkbox-box .n-checkbox-icon{transform:rotate(-12deg) translate(.5px,1px)}#setting-city{display:inline-block;color:var(--primaryColor)}#setting-city:hover{cursor:pointer}#setting-city svg{transition:all .3s;transform:translateY(3px);font-size:16px}#component_list_vue_app{height:28px;width:400px}#component_list_vue_app .n-base-selection-label{height:28px}#version_list_vue_app{height:28px;width:400px}#version_list_vue_app .n-base-selection-label{height:28px}#cc_list_vue_app{height:28px;width:400px}#cc_list_vue_app .n-base-selection-label{height:28px}#newcc_list_vue_app{height:28px;width:400px}#newcc_list_vue_app .n-base-selection-label{height:28px}#feature_list_vue_app{height:28px;min-width:200px;max-width:800px;width:100%}#feature_list_vue_app .n-base-selection-label{height:28px}#search_history_list_vue_app_top,#search_history_list_vue_app_bottom{height:28px;width:120px;max-width:200px}#search_history_list_vue_app_top .n-base-selection-label,#search_history_list_vue_app_bottom .n-base-selection-label{height:28px;border-radius:4px}#comp_desc_container{display:none}#comp_desc{height:fit-content}.validation_error_text{font-size:12px;color:#e80505;font-weight:400}.bug-new_filename{color:gray;font-weight:600;margin-left:6px}.collection-list-title:hover{cursor:pointer;color:var(--primaryColor)}#titles #subtitle{font-weight:600}.bz_alias_short_desc_container.edit_form{padding:10px}.margin-0{margin:0}.mt-5{margin-top:5px}.ml-5{margin-left:5px}.mr-5{margin-right:5px}.mb-5{margin-bottom:5px}.n-base-selection-placeholder{font-size:12px}.bz_comment.bz_first_comment .bz_comment_text p{margin-block-start:0;margin-block-end:0}.clear-br-label{-webkit-user-select:none;user-select:none}.clear-br-label:hover{cursor:pointer;color:var(--primaryColorHover)}'; importCSS(indexLess); var CDNScriptURLEnum = ((CDNScriptURLEnum2) => { CDNScriptURLEnum2["MONACO"] = "https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.52.0/min/vs/loader.min.js"; CDNScriptURLEnum2["VUE"] = "https://cdnjs.cloudflare.com/ajax/libs/vue/3.5.13/vue.global.prod.min.js"; CDNScriptURLEnum2["NAIVE_UI"] = "https://cdnjs.cloudflare.com/ajax/libs/naive-ui/2.40.1/index.prod.js"; CDNScriptURLEnum2["CRYPTO_JS"] = "https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.2.0/crypto-js.min.js"; return CDNScriptURLEnum2; })(CDNScriptURLEnum || {}); const PATHNAME = window.location.pathname; const ZHOU_OF_WEEK_MAP = { SUNDAY: "周日", MONDAY: "周一", TUESDAY: "周二", WEDNESDAY: "周三", THURSDAY: "周四", FRIDAY: "周五", SATURDAY: "周六" }; const XINGQI_OF_WEEK_MAP = { SUNDAY: "星期日", MONDAY: "星期一", TUESDAY: "星期二", WEDNESDAY: "星期三", THURSDAY: "星期四", FRIDAY: "星期五", SATURDAY: "星期六" }; var PathNameEnum = ((PathNameEnum2) => { PathNameEnum2["BUG_LIST"] = "/bugzilla/buglist.cgi"; PathNameEnum2["BUG_DETAIL"] = "/bugzilla/show_bug.cgi"; PathNameEnum2["BUG_NEW"] = "/bugzilla/enter_bug.cgi"; PathNameEnum2["BUG_NEW_ENTRY"] = "/bugzilla/describecomponents.cgi"; PathNameEnum2["BUG_ATTACHMENT"] = "/bugzilla/attachment.cgi"; PathNameEnum2["BUG_HISTORY"] = "/bugzilla/show_activity.cgi"; PathNameEnum2["BUG_PROCESS"] = "/bugzilla/process_bug.cgi"; return PathNameEnum2; })(PathNameEnum || {}); function $(selector, context = document) { return context.querySelector(selector); } function $$(selector, context = document) { return Array.from(context.querySelectorAll(selector)); } const renderBugAttachment = () => { const attachmentSubmit = $(".attachment_entry input[value='Submit']"); if (attachmentSubmit) { attachmentSubmit.classList.add("custom-button"); } }; const renderBugAttachmentPage = () => { if (PATHNAME === PathNameEnum.BUG_ATTACHMENT) { renderBugAttachment(); } }; const PERSONS_MAP = { anbin: "安斌", anna: "柏红梅", annabai: "柏红梅", BrukcalLi: "李林浩", lilinhao: "李林浩", cehn: "王笑晨", cehnwang: "王笑晨", cesar: "陈述", cesarchen: "陈述", cherry: "兰春花", Cherrylan: "兰春花", chuwanting: "储婉婷", chenxiaoxia: "陈晓霞", dizizhao: "狄子钊", dingjiaju: "丁佳驹", fiona: "牟卫灵", fionam: "牟卫灵", frank: "席小丁", frankxi: "席小丁", xiwenge: "郗文革", fuge: "付戈", harehe: "何小波", huanglin: "黄林", huangqing: "黄青", huangxudong: "黄旭东", huangyifei: "黄一非", huangyueqi: "黄月琪", huangyou: "黄友", humming: "马云", hummingma: "马云", huqing: "胡青", jenny: "王亮", jennywang: "王亮", jiangqianqian: "姜倩倩", jiangjiacheng: "蒋佳成", jizeyu: "纪泽宇", joe: "周强", zhouqiang: "周强", jose: "赖振海", joselai: "赖振海", kevin: "张亚峰", lidehua: "李德华", lifuyi: "李福一", lihaichuan: "李海川", liju: "李桔", lilei: "李雷", linchao: "林超", lisa: "姚艳丽", lisayao: "姚艳丽", liubowen: "刘博文", liuxu: "刘旭", liuyicheng: "刘伊铖", lixianxiang: "李先祥", lixiaoyi: "李小益", liyandong: "李彦东", lucy: "赵亚兰", lucyzhao: "赵亚兰", luoshengming: "罗圣明", magina: "刘松平", maginaliu: "刘松平", Majun: "马军", majun: "马军", mandyyang: "杨曼", maqingbin: "马庆宾", mijie: "米杰", sandywang: "王硕", shenbei: "申倍", demanshen: "申倍", shenfangshuai: "申方帅", shenxiang: "沈祥", shikun: "石坤", larryshi: "石坤", liutianrui: "刘添瑞", sunfeng: "孙丰", stevensun: "孙丰", shizhipeng: "石志鹏", songjie: "宋杰", steven: "刘洋", stevenliu: "刘洋", talk: "陈涛", talkchen: "陈涛", tangshuangxiao: "唐霜晓", tianmaosheng: "田茂生", una: "高秋涵", Unagao: "高秋涵", vern: "张超", Vernzhang: "张超", wangdandan: "王丹丹", wangfeiyan: "王飞燕", wanghairong: "王海容", wuguangmin: "吴光敏", wangshijie: "王世杰", wangyi: "王屹", weiliangpeng: "韦良鹏", wendy: "吴红省", wuhaidong: "吴海东", wuhongsheng: "吴红省", wendywu: "吴红省", xuhang: "徐航", yanghuanhuan: "杨欢欢", yangmingxuan: "杨明轩", yanieye: "叶伟", yafengzhang: "张亚峰", yihuan: "王义欢", yihuanwang: "王义欢", zengchenglong: "曾成龙", zhangrunsheng: "张润生", gausszhang: "张润生", zhangyingqi: "张莹琦", zhangzheyi: "张喆懿", zhaozuwen: "赵祖雯", zhengsong: "郑松", "zhengsong.ext": "郑松", zhoulin: "周林", zhuhewei: "朱赫伟", test: "永洪测试", yonghong: "永洪测试", yonghongcode: "永洪测试", yonghongdoc: "永洪测试" }; const FORM_ITEM_1 = [ { show: true, disabled: false, value: "#bz_show_bug_column_1 tr:has(td[id='bz_field_status'])", label: "Status" }, { show: true, disabled: false, value: "#bz_show_bug_column_1 tr:has(td[id='field_container_product'])", label: "Product" }, { show: true, disabled: false, value: "#bz_show_bug_column_1 tr:has(td[id='field_container_component'])", label: "Component" }, { show: true, disabled: true, value: "#bz_show_bug_column_1 tr:has(th[id='field_label_version'])", label: "Version" }, { show: true, disabled: false, value: "#bz_show_bug_column_1 tr:has(th[id='field_label_rep_platform'])", label: "Hardware" }, { show: true, disabled: false, value: "#bz_show_bug_column_1 tr:has(label[for='priority'])", label: "Importance" }, { show: true, disabled: true, value: "#bz_show_bug_column_1 tr:has(td[class='bz_assignee_td'])", label: "Assigned To" }, { show: true, disabled: false, value: "#bz_show_bug_column_1 tr:has(th[id='field_label_bug_file_loc'])", label: "URL" }, { show: true, disabled: false, value: "#bz_show_bug_column_1 tr:has(th[id='field_label_tag'])", label: "Tags" }, { show: true, disabled: false, value: "#bz_show_bug_column_1 tr:has(th[id='field_label_dependson'])", label: "Depends on" }, { show: true, disabled: false, value: "#bz_show_bug_column_1 tr:has(th[id='field_label_blocked'])", label: "Blocks" } ]; const FORM_ITEM_2 = [ { show: true, disabled: true, value: "#bz_show_bug_column_2 table tr:first-child", label: "Reported" }, { show: true, disabled: true, value: "#bz_show_bug_column_2 table tr:nth-child(2)", label: "Modified" }, { show: true, disabled: false, value: "#bz_show_bug_column_2 table tr:nth-child(3)", label: "CC List" }, { show: true, disabled: false, value: "#bz_show_bug_column_2 table tr:nth-child(5)", label: "See Also" }, { show: true, disabled: false, value: "#bz_show_bug_column_2 table tr:nth-child(6)", label: "Bug类型1" }, { show: true, disabled: false, value: "#bz_show_bug_column_2 table tr:nth-child(7)", label: "Bug类型2" }, { show: true, disabled: false, value: "#bz_show_bug_column_2 table tr:nth-child(8)", label: "请选择Feature号" }, { show: true, disabled: false, value: "#bz_show_bug_column_2 table tr:nth-child(9)", label: "是否有Matrix/Case覆盖" }, { show: true, disabled: false, value: "#bz_show_bug_column_2 table tr:nth-child(10)", label: "TestCase类型" }, { show: true, disabled: false, value: "#bz_show_bug_column_2 table tr:nth-child(11)", label: "客户是否也发现了这个问题" }, { show: true, disabled: false, value: "#bz_show_bug_column_2 table tr:nth-child(12)", label: "公司名称" }, { show: true, disabled: false, value: "#bz_show_bug_column_2 table tr:nth-child(13)", label: "问题复杂度" }, { show: true, disabled: false, value: "#bz_show_bug_column_2 table tr:nth-child(14)", label: "Bug提报时的版本状态" }, { show: true, disabled: false, value: "#bz_show_bug_column_2 table tr:nth-child(15)", label: "Bug产生原因(开发人员填写)" }, { show: true, disabled: false, value: "#bz_show_bug_column_2 table tr:nth-child(16)", label: "Bug产生细节原因(开发人员填写)" }, { show: true, disabled: false, value: "#bz_show_bug_column_2 table tr:nth-child(17)", label: "如果是改出来的Bug,填入是谁改出来的(开发人员填写)" }, { show: true, disabled: false, value: "#bz_show_bug_column_2 table tr:nth-child(18)", label: "如果是改出来的Bug,填入Bug号或Feature号(开发人员填写)" }, { show: true, disabled: true, value: "#bz_show_bug_column_2 table tr:nth-child(19)", label: "影响范围和测试建议(开发人员填写)" }, { show: true, disabled: false, value: "#bz_show_bug_column_2 table tr:nth-child(20)", label: "Bug被Reopen原因" }, { show: true, disabled: false, value: "#bz_show_bug_column_2 table tr:nth-child(21)", label: "对应testlink用例编号" } ]; const COMMENT_DEFAULT_TEMPLATE_1 = ` 📌【复现条件】 ───────────────────────────── 🔍【复现步骤】 ───────────────────────────── 1. 2. ✅【预期结果】 ───────────────────────────── ❌【实际结果】 ───────────────────────────── 💡【备注信息】 ───────────────────────────── `; const COMMENT_DEFAULT_TEMPLATE_2 = ` 📌【复现条件】 ───────────────────────────── 🔍【复现步骤】 ───────────────────────────── 1. 2. ✅【预期结果】 ───────────────────────────── ❌【实际结果】 ───────────────────────────── 💡【备注信息】 ───────────────────────────── `; const BUG_STATUS = { VERIFIED: "VERIFIED", RESOLVED: "RESOLVED", CLOSED: "CLOSED" }; const RESOLUTION = { FIXED: "FIXED" }; const STORAGE_KEY_MAP = { COLLECTED_BUGS: "collectedBugs", PERSONS_MAP: "personsMap", QUIP_TYPE: "quipType", COMPLETED_BUGS: "completedBugs", CITY: "city", FORM_ITEM_CONTROL: "formItemControl", CUSTOM_BRANCHES: "customBranches", NEW_BUG_COMMENT_TEMPLATE: "newBugCommentTemplate", LIST_PAGE_ACTION_BTNS: "listPageActionBtns", HASCLEAR_COMPLETED_BUGS: "hasClearCompletedBugs", SEARCH_HISTORY: "searchHistory", QUICK_SUMMARY: "quickSummary", GITLAB_CONFIG: "gitlabConfig", HAS_AUTO_SYNC_PERSON_MAP: "hasAutoSyncPersonMap", PAGE_DETAIL_CONTROL: "pageDetailControl", AUTO_SYNC_LOCAL_DATA_TO_CLOUD: "autoSyncLocalDataToCloud", KEEP_REPORT_BUGS_DAYS: "keepReportBugsDays" }; const GITLAB_ORIGIN = "http://192.168.1.180:8888"; const FIRE_BASE_SCRIPT_URL = { APP: "https://www.gstatic.com/firebasejs/10.7.1/firebase-app-compat.js", AUTH: "https://www.gstatic.com/firebasejs/10.7.1/firebase-auth-compat.js", DATABASE: "https://www.gstatic.com/firebasejs/10.7.1/firebase-database-compat.js" }; const FIRE_BASE_CONFIG = { apiKey: "AIzaSyCuNIxlkvH6zV-V_Ashi0y7-l1ihAaHEu8", authDomain: "bugzilla-6ecaf.firebaseapp.com", databaseURL: "https://bugzilla-6ecaf-default-rtdb.asia-southeast1.firebasedatabase.app", projectId: "bugzilla-6ecaf", storageBucket: "bugzilla-6ecaf.firebasestorage.app", messagingSenderId: "81688421567", appId: "1:81688421567:web:c94cb82be4131a8540920a" }; const showMessage = (type, message, duration = 2e3) => { const existMessageNode = $(".global-message"); if (existMessageNode) { document.body.removeChild(existMessageNode); } const svgSuccess = ``; const svgError = ``; const svgMap = new Map([ ["success", svgSuccess], ["error", svgError] ]); const innerHTML = ` ${svgMap.get(type)} `; const messageNode = document.createElement("div"); let timer = null; messageNode.classList.add("global-message"); messageNode.innerHTML = innerHTML; document.body.appendChild(messageNode); timer = setTimeout(() => { const animation = messageNode.animate( [ { opacity: 1, top: "30px" }, { opacity: 0, top: "10px" } ], { duration: 500, easing: "ease-in-out", fill: "forwards" } ); animation.onfinish = () => { var _a; animation.cancel(); messageNode && ((_a = document.body) == null ? void 0 : _a.removeChild(messageNode)); clearTimeout(timer); }; }, duration); return () => { var _a; messageNode && ((_a = document.body) == null ? void 0 : _a.removeChild(messageNode)); clearTimeout(timer); }; }; const showSuccessMessage = (message, duration = 2e3) => { return showMessage("success", message, duration); }; const showErrorMessage = (message, duration = 2e3) => { return showMessage("error", message, duration); }; const getCollectedBugs = () => { var _a; return ((_a = JSON.parse(localStorage.getItem(STORAGE_KEY_MAP.COLLECTED_BUGS) ?? "{}")) == null ? void 0 : _a.list) ?? []; }; const getCollectInfo = (id) => { const collectedBugs = getCollectedBugs(); const hasCollected = collectedBugs.length && collectedBugs.some((bug) => bug.id.includes(id)); return { collectedBugs, hasCollected }; }; const deleteCollectedBug = (id) => { const collectedBugs = getCollectedBugs(); const newCollectedBugs = collectedBugs.filter((bug) => !bug.id.includes(id)); localStorage.setItem(STORAGE_KEY_MAP.COLLECTED_BUGS, JSON.stringify({ list: newCollectedBugs })); }; const setCollectionBug = (id, title, url) => { const { collectedBugs = [], hasCollected } = getCollectInfo(id); if (hasCollected) { showErrorMessage("此bug已收藏"); return; } collectedBugs.push({ id, title, url }); localStorage.setItem(STORAGE_KEY_MAP.COLLECTED_BUGS, JSON.stringify({ list: collectedBugs })); showSuccessMessage("收藏成功"); }; const setCollectionIcon = (collectionNode, id) => { if (!collectionNode) { return; } collectionNode.innerHTML = getCollectInfo(id).hasCollected ? ` ` : ` `; }; const preventBoom = (fun, ...args) => { if (fun && typeof fun === "function") { return fun(...args); } }; const createDialog = ({ title = "", body, footer, maskTransparent = false, okText = "确定", cancelText = "取消", onOk, onCancel, hideOk = false, hideCancel = false, className = "", bodyClassName = "", style = "", bodyStyle = "", autoFullScreen = false, onMount = () => { }, onDestroy = () => { } }) => { let storeDialogWidth = 0; let storeDialogHeight = 0; let isDialogFullScreen = void 0; let isDragging = false; let startX = 0; let startY = 0; let dialogStartX = 0; let dialogStartY = 0; const titleTransformWidthMap = new Map([ [1, 8], [2, 20], [3, 32] ]); const existDialogNodes = $$(".global-dialog"); const length = existDialogNodes.length; const zIndex = 900 + length; const maskNode = document.createElement("div"); maskTransparent && maskNode.classList.add("global-dialog-mask-transparent"); const dialogNode = document.createElement("div"); const header = document.createElement("div"); header.style.display = "flex"; header.style.alignItems = "center"; const dialogBody = document.createElement("div"); const headerBtn = document.createElement("div"); headerBtn.style.display = "inline-block"; const headerTitle = document.createElement("div"); const titleNode = document.createElement("div"); headerTitle.classList.add("flex-center"); headerTitle.style.flex = "1"; if (!autoFullScreen && !isDialogFullScreen) { headerTitle.style.cursor = "move"; } headerTitle.appendChild(titleNode); titleNode.style.userSelect = "none"; titleNode.innerText = title; const closeBtn = document.createElement("span"); closeBtn.title = "关闭弹窗(Esc)"; const exitFullScreenBtn = document.createElement("span"); exitFullScreenBtn.title = "退出全屏"; const fullScreenBtn = document.createElement("span"); fullScreenBtn.title = "全屏显示"; const closeIcon = ``; const exitFullScreenIcon = ``; const fullScreenIcon = ``; closeBtn.innerHTML = closeIcon; closeBtn.classList.add("control-btn"); closeBtn.classList.add("close-btn"); exitFullScreenBtn.innerHTML = exitFullScreenIcon; exitFullScreenBtn.classList.add("control-btn"); exitFullScreenBtn.classList.add("exit-full-screen-btn"); fullScreenBtn.innerHTML = fullScreenIcon; fullScreenBtn.classList.add("control-btn"); fullScreenBtn.classList.add("full-screen-btn"); const resizeObserver = new ResizeObserver((entries) => { for (const entry of entries) { if (!isDialogFullScreen) { storeDialogWidth = entry.contentRect.width; storeDialogHeight = entry.contentRect.height; } else { dialogBody.style.width = "100%"; if (dialogBody == null ? void 0 : dialogBody.firstChild) { const firstChild = dialogBody.firstChild; firstChild.style = firstChild.style ?? ""; firstChild.style.width = "100%"; firstChild.style.height = "100%"; } } } }); resizeObserver.observe(dialogNode); const closeDialog = () => { document.removeEventListener("keydown", enterEvent); document.removeEventListener("keydown", escEvent); document.removeEventListener("mousemove", dragMove); document.removeEventListener("mouseup", dragEnd); const animation2 = dialogNode.animate( [ { opacity: 1, transition: "transition: opacity 0.5s ease-in-out, top 0.5s ease-in-out;" }, { opacity: 0, transition: "transition: opacity 0.5s ease-in-out, top 0.5s ease-in-out;" } ], { duration: 500, easing: "ease-in-out", fill: "forwards" } ); animation2.onfinish = () => { animation2.cancel(); document.body.removeChild(maskNode); const dialogs = $$(".global-dialog"); if (dialogs.length === 0) { document.body.style.overflow = "auto"; } isDialogFullScreen = false; resizeObserver.disconnect(); onDestroy(); }; }; closeBtn.addEventListener("click", () => { closeDialog(); }); exitFullScreenBtn.addEventListener("click", () => { if (isDialogFullScreen) { headerTitle.style.cursor = "move"; isDialogFullScreen = false; dialogNode.style.width = `${Math.ceil(storeDialogWidth)}px`; dialogNode.style.height = `${Math.ceil(storeDialogHeight)}px`; dialogNode.style.transform = "translate(-50%, -50%)"; dialogNode.style.left = "50%"; dialogNode.style.top = "50%"; dialogNode.style.margin = "0"; } }); fullScreenBtn.addEventListener("click", () => { if (!isDialogFullScreen) { headerTitle.style.cursor = "auto"; isDialogFullScreen = true; dialogNode.style.width = "100%"; dialogNode.style.height = "99.6%"; dialogNode.style.transform = "translate(-50%, -50.4%)"; dialogNode.style.left = ""; dialogNode.style.top = ""; dialogNode.style.margin = "0"; dialogBody.style.width = "100%"; dialogBody.style.height = "100%"; } }); if (autoFullScreen) { fullScreenBtn.click(); } headerBtn.appendChild(closeBtn); if (!autoFullScreen) { headerBtn.appendChild(exitFullScreenBtn); headerBtn.appendChild(fullScreenBtn); } header.appendChild(headerBtn); titleNode.style.transform = `translateX(-${titleTransformWidthMap.get(headerBtn.children.length)}px)`; header.appendChild(headerTitle); header.classList.add("global-dialog-header"); dialogBody.classList.add("global-dialog-body"); const footerInner = document.createElement("div"); maskNode.classList.add("global-dialog-mask"); dialogNode.classList.add("global-dialog"); if (className) { dialogNode.classList.add(className); } if (style) { dialogNode.style = style; } if (bodyClassName) { dialogBody.classList.add(bodyClassName); } if (bodyStyle) { dialogBody.style = bodyStyle; } if (typeof footer === "string") { footerInner.innerHTML = footer; } else if (footer) { footerInner.appendChild(footer); } else if (footer !== false && footer !== null) { footerInner.classList.add("global-dialog-footer"); if (!hideOk) { const footerSaveBtn = document.createElement("div"); footerSaveBtn.classList.add("custom-button"); footerSaveBtn.innerText = okText + " (Enter)"; footerSaveBtn.addEventListener("click", () => { preventBoom(onOk, closeDialog); }); footerInner.appendChild(footerSaveBtn); } if (!hideCancel) { const footerCancelBtn = document.createElement("div"); footerCancelBtn.classList.add("custom-button"); footerCancelBtn.classList.add("plain-button"); footerCancelBtn.innerText = cancelText + " (Esc)"; footerCancelBtn.addEventListener("click", async () => { const res = await preventBoom(onCancel) ?? true; if (res) { closeDialog(); } }); footerInner.appendChild(footerCancelBtn); } } if (typeof body === "string") { dialogBody.innerHTML = body; } else { dialogBody.appendChild(body); } dialogNode.appendChild(header); dialogNode.appendChild(dialogBody); dialogNode.appendChild(footerInner); maskNode.style.zIndex = `${zIndex}`; maskNode.appendChild(dialogNode); document.body.appendChild(maskNode); document.body.style.overflow = "hidden"; const animation = dialogNode.animate( [ { opacity: 0, top: "46%", transition: "transition: opacity 0.5s ease-in-out, top 0.5s ease-in-out;" }, { opacity: 1, top: "50%", transition: "transition: opacity 0.5s ease-in-out, top 0.5s ease-in-out;" } ], { duration: 500, easing: "ease-in-out", fill: "forwards" } ); animation.onfinish = () => { animation.cancel(); }; const escEvent = (e) => { if (e.key === "Escape") { closeDialog(); } }; const enterEvent = (e) => { if (e.key === "Enter") { preventBoom(onOk, closeDialog); } }; const dragStart = (e) => { if (isDialogFullScreen) return; isDragging = true; startX = e.clientX; startY = e.clientY; document.body.style.userSelect = "none"; const rect = dialogNode.getBoundingClientRect(); dialogStartX = rect.left; dialogStartY = rect.top; }; const dragEnd = () => { isDragging = false; document.body.style.userSelect = "auto"; }; const dragMove = (e) => { if (!isDragging || isDialogFullScreen) return; const dx = e.clientX - startX; const dy = e.clientY - startY; const newLeft = dialogStartX + dx; const newTop = dialogStartY + dy; const windowWidth = window.innerWidth; const windowHeight = window.innerHeight; const dialogWidth = dialogNode.offsetWidth; const dialogHeight = dialogNode.offsetHeight; const clampedLeft = Math.max(0, Math.min(newLeft, windowWidth - dialogWidth)); const clampedTop = Math.max(0, Math.min(newTop, windowHeight - dialogHeight)); dialogNode.style.left = `${clampedLeft}px`; dialogNode.style.top = `${clampedTop}px`; dialogNode.style.transform = "none"; dialogNode.style.margin = "0"; }; document.addEventListener("keydown", enterEvent); document.addEventListener("keydown", escEvent); headerTitle.addEventListener("mousedown", dragStart); document.addEventListener("mousemove", dragMove); document.addEventListener("mouseup", dragEnd); onMount(); return closeDialog; }; const debounce = (func, delay) => { let timer; return (...args) => { if (timer) { clearTimeout(timer); } timer = setTimeout(() => { func.apply(void 0, args); }, delay); }; }; const bugCollectionDialog = () => { let appIns = null; const appId = "bug_collection_vue_app"; createDialog({ title: "收藏列表", hideOk: true, cancelText: "关闭", bodyStyle: "width: 60vw; height: 60vh;", body: `
`, onMount: () => { const collectedBugs = getCollectedBugs(); const { createApp, ref, h } = Vue; const app = createApp({ template: `]*>)([\s\S]*?)(<\/pre>)/g, (_match, preOpen, preContent, preClose) => {
const replacedContent = replaceHashInPreContent(preContent);
return `${preOpen}${replacedContent}${preClose}`;
});
}
if (target instanceof HTMLElement) {
let domElements;
if (["PRE", "DIV"].includes(target.tagName)) {
domElements = [target];
} else {
domElements = $$("pre", target);
if (domElements.length === 0) {
domElements = $$("div", target);
}
}
domElements.forEach((domElement) => {
const originalHtml = domElement.innerHTML;
const newHtml = replaceHashInPreContent(originalHtml);
domElement.innerHTML = newHtml;
const hashLinks = $$(".commit-hash-link", domElement);
hashLinks.forEach((link) => {
link.addEventListener("click", (e) => {
e.preventDefault();
const hash = link.dataset.hash || "";
const projectName = link.dataset.project || "";
customClickHandler(e, hash, projectName);
});
});
});
return;
}
throw new Error("target 必须是 HTML 字符串或 HTMLElement 类型");
};
const openGitlabByHash = (hash, projectName) => {
window.open(`${GITLAB_ORIGIN}/project/${projectName}/-/commit/${hash}`, "_blank");
};
const onFormSubmit = (form, isFinish, id, title) => {
if (form) {
if (isFinish) {
const bug = {
id,
name: title,
url: window.location.href
};
addBugWithRepeatCheck(bug, getTodayDate(), true);
updateCompleteBugs(id);
}
form.submit();
}
};
const viewImageFullScreen = (parentElement) => {
if (!parentElement) {
return;
}
const imgs = $$("img", parentElement);
imgs.forEach((img) => {
img.style.cursor = "zoom-in";
img.title = "点击图片全屏查看";
const imgCloned = img.cloneNode(true);
imgCloned.title = "点击图片关闭弹窗";
img.addEventListener("click", () => {
const closeDialog = createDialog({
title: "查看图片(点击图片关闭弹窗)",
body: imgCloned,
autoFullScreen: true,
hideOk: true,
cancelText: "关闭"
});
imgCloned.addEventListener("click", () => {
closeDialog();
});
});
});
};
const createButton = (text, insertFn, clickFn) => {
const button = document.createElement("div");
button.classList.add("custom-button");
button.innerText = text;
button.addEventListener("click", (e) => clickFn(e, button));
insertFn(button);
return button;
};
const clearTextNode = (targetNode) => {
const childNodes = Array.from(targetNode.childNodes);
childNodes.forEach((node) => {
var _a;
if (node.nodeType === 3) {
const textContent = (_a = node == null ? void 0 : node.textContent) == null ? void 0 : _a.trim();
if (textContent) {
targetNode.removeChild(node);
} else {
node.textContent = "";
}
}
});
};
const downloadResource = (url, filename = "download") => {
const a = document.createElement("a");
a.style.display = "none";
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
};
function iframeCallback(iframeId, callback) {
const iframePage = $("#" + iframeId);
if (iframePage) {
iframePage.onload = () => {
const contentDocument = iframePage.contentDocument;
callback(contentDocument);
};
}
}
const renderBugDetail = () => {
var _a, _b, _c, _d;
const persons = getPersonMap();
const table1 = $("#bz_show_bug_column_1");
const table2 = $("#bz_show_bug_column_2");
const reporterNode = $("#bz_show_bug_column_2 .vcard .email");
const table2AllRows = $$("tr", table2);
const reporterEmail = getPersonEmail((reporterNode == null ? void 0 : reporterNode.href) ?? "");
const reportNodes = $$(".vcard .email .fn");
const historyBtn = $("#bz_show_bug_column_2 tr:nth-child(2) a");
const editTitleBtn = $("#editme_action");
const assigneeEditBtn = $("#bz_assignee_edit_action");
const assigneeTakeBtn = $("#bz_assignee_take_action");
const markDuplicateBtn = $("#dup_id_discoverable_action");
const markDuplicateBox = $("#dup_id_discoverable");
const duplicateSettings = $("#duplicate_settings");
const replaceTitleInput = $("#summary_alias_input");
const commentTextArea = $("#comment");
const commentBox = $("#add_comment");
const commentBoxLabel = $("#add_comment label");
const attachmentDetails = $$("#attachment_table td[valign='top']:nth-child(2) a");
const saveFormBtn1 = $(".bz_alias_short_desc_container .knob-buttons input");
const saveFormBtn2 = $("#add_comment .knob-buttons input");
const bugStatus = $("#bug_status");
const resolution = $("#resolution");
const resolutionSettings = $("#resolution_settings");
const assigneeInputNode = $("#bz_assignee_input");
const assigneeEditNode = $("#bz_assignee_edit_container");
const assignToSelect = $("#assigned_to");
const bugTitleBox = $("#summary_alias_container");
const bugTitleNode = $("#short_desc_nonedit_display");
const bugIDNode = $(".bz_alias_short_desc_container a b");
const bugId = (_a = ((bugIDNode == null ? void 0 : bugIDNode.innerText) ?? "").match(/(\d+)$/)) == null ? void 0 : _a[1];
const effectNode = $("#cf_effect");
const bzSpacerNodes = $$("#bz_show_bug_column_1 tr:has(td[class='bz_section_spacer'])");
const navigationNode = $(".navigation");
const attachmentNode = $("#attachment_table .bz_attach_footer a:not(a[id='view_all'])");
const attachmentViewAll = $("#attachment_table .bz_attach_footer a[id='view_all']");
const navigationABtns = $$("#bugzilla-body .navigation a");
const navigationFontBtns = $$("#bugzilla-body .navigation i font");
const commentNodes = $$("#comments .bz_comment_table .bz_comment:not(.bz_first_comment) .bz_comment_text");
const firstComment = $(".bz_comment.bz_first_comment .bz_comment_text");
let completeBtn = null;
if (table1 && table2) {
const table1Width = table1.clientWidth;
table2.style.setProperty("width", Math.round(document.body.clientWidth - table1Width) + "px");
}
if (historyBtn) {
historyBtn.innerText = "流转历史";
historyBtn.classList.add("custom-button");
historyBtn.classList.add("plain-button");
historyBtn.style.margin = "0 6px";
historyBtn.addEventListener("click", (e) => {
e.preventDefault();
createDialog({
title: "流转历史",
hideOk: true,
cancelText: "关闭",
bodyStyle: "width: 60vw; height: 60vh;",
body: `
`,
onMount: () => {
iframeCallback("history-iframe", (contentDocument) => {
const header = $("#header", contentDocument);
const footer = $("#footer", contentDocument);
if (header) {
header.remove();
}
if (footer) {
footer.remove();
}
});
}
});
});
}
reportNodes.forEach((node) => {
if (Object.keys(persons).includes(node.innerText)) {
node.innerText = persons[node.innerText];
} else if (node.innerText.includes("-")) {
const splits = node.innerText.split("-");
const left = splits[0];
const right = splits[1];
if (/^[a-zA-Z0-9]+$/.test(left)) {
node.innerText = persons[left];
}
if (/^[a-zA-Z0-9]+$/.test(right)) {
node.innerText = persons[right];
}
}
});
createButton(
"复制报告人姓名",
(button) => {
var _a2;
button.classList.add("plain-button");
(_a2 = reporterNode == null ? void 0 : reporterNode.parentNode) == null ? void 0 : _a2.insertBefore(button, reporterNode.nextSibling);
},
() => {
copyText(reporterNode.innerText);
}
);
if (bzSpacerNodes.length) {
bzSpacerNodes.forEach((node) => {
node.style.display = "none";
});
}
if (effectNode && !effectNode.value) {
effectNode.value = "本 case";
}
if (bugTitleBox && bugTitleNode && bugIDNode) {
const reportBtn = createButton(
"日报/移除",
(button) => {
button.classList.add("custom-button");
if (!isBugInReport(bugId)) {
button.innerText = "添加日报";
button.style.setProperty("border", "1px solid rgb(200, 200, 200)");
} else {
button.classList.add("plain-button");
button.innerText = "移除日报";
button.style.setProperty("border", "1px solid #cccccc");
}
bugTitleBox.parentNode.insertBefore(button, bugTitleBox.nextSibling);
},
() => {
if (!isBugInReport(bugId)) {
addBugWithRepeatCheck({
id: bugId,
name: bugTitleNode.innerText,
url: window.location.href
});
reportBtn.classList.add("plain-button");
reportBtn.innerText = "移除日报";
} else {
removeBugFromReport(bugId);
reportBtn.classList.remove("plain-button");
reportBtn.innerText = "添加日报";
}
}
);
createButton(
"复制 COMMIT",
(button) => {
button.classList.add("plain-button");
bugTitleBox.parentNode.insertBefore(button, bugTitleBox.nextSibling);
},
() => {
copyText(`git commit -m "bug: ${bugId} 修复:${bugTitleNode.innerText}"`);
}
);
createButton(
"复制 ID",
(button) => {
button.classList.add("plain-button");
bugTitleBox.parentNode.insertBefore(button, bugTitleBox.nextSibling);
},
() => {
copyText(bugId);
}
);
}
if (assigneeInputNode) {
assigneeInputNode.parentNode.classList.add("bz_assignee_td");
const backButton = createButton(
"取消",
(button) => {
button.classList.add("plain-button");
button.style.display = "none";
button.style.marginRight = "0";
assigneeInputNode.parentNode.appendChild(button);
},
(_, button) => {
assigneeInputNode.classList.add("bz_default_hidden");
assigneeEditNode.classList.remove("bz_default_hidden");
if (button.style.display === "block") {
button.style.display = "none";
const aLink = $("#bz_assignee_edit_container .email");
if (aLink) {
const email = getPersonEmail(aLink.href);
if (email) {
assignToSelect.value = email;
const assignToAppNode = $("#assigned_to_list_vue_app");
if (assignToAppNode) {
assignToAppNode.remove();
assignToList();
}
}
}
}
}
);
if (editTitleBtn) {
bugTitleBox.classList.remove("bz_default_hidden");
replaceTitleInput.classList.add("bz_default_hidden");
editTitleBtn.innerText = "编辑标题";
editTitleBtn.classList.add("custom-button");
editTitleBtn.classList.add("plain-button");
editTitleBtn.addEventListener("click", (e) => {
e.preventDefault();
bugTitleBox.classList.remove("bz_default_hidden");
replaceTitleInput.classList.add("bz_default_hidden");
const alias = $("#alias", replaceTitleInput);
const shortDesc = $("#short_desc", replaceTitleInput);
const replaceClone = replaceTitleInput.cloneNode(true);
replaceClone.classList.remove("bz_default_hidden");
const aliasInput = $("#alias", replaceClone);
const shortDescInput = $("#short_desc", replaceClone);
if (aliasInput) {
aliasInput.addEventListener("input", (e2) => {
alias.value = e2.target.value;
});
}
if (shortDescInput) {
shortDescInput.addEventListener("input", (e2) => {
shortDesc.value = e2.target.value;
});
}
createDialog({
title: "更改标题",
body: replaceClone,
okText: "保存",
onOk: (closeDialog) => {
onFormSubmit(saveFormBtn1.form, false);
closeDialog();
}
});
});
}
if (assigneeEditBtn) {
assigneeEditBtn.innerText = "加载资源中...";
assigneeEditBtn.classList.add("custom-button");
assigneeEditBtn.classList.add("plain-button");
assigneeEditBtn.classList.add("disabled-button");
assigneeEditBtn.addEventListener("click", () => {
var _a2;
assigneeInputNode.classList.remove("bz_default_hidden");
assigneeEditNode.classList.add("bz_default_hidden");
if (assignToSelect.nextElementSibling.tagName === "BR") {
(_a2 = assignToSelect.nextElementSibling) == null ? void 0 : _a2.remove();
}
if (backButton.style.display === "none") {
backButton.style.display = "block";
}
});
}
if (assigneeTakeBtn) {
assigneeTakeBtn.classList.add("bz_default_hidden");
const takeNode = document.createElement("span");
takeNode.innerText = "转给自己";
takeNode.classList.add("custom-button");
takeNode.classList.add("plain-button");
const assignToPerson = assignToSelect.value;
(_b = assigneeTakeBtn.parentNode) == null ? void 0 : _b.insertBefore(takeNode, assigneeTakeBtn.nextSibling);
takeNode.addEventListener("click", () => {
createDialog({
body: "确定将此任务转给自己?",
bodyStyle: "width: 400px; height: 50px;",
okText: "确定",
onOk: (closeDialog) => {
var _a2;
assigneeTakeBtn.click();
closeDialog();
(_a2 = $("br", assigneeInputNode)) == null ? void 0 : _a2.remove();
onFormSubmit(saveFormBtn1.form, false);
},
onDestroy: () => {
assigneeInputNode.classList.add("bz_default_hidden");
assigneeEditNode.classList.remove("bz_default_hidden");
assignToSelect.value = assignToPerson;
}
});
});
}
}
if (bugStatus && resolution && markDuplicateBox) {
const status1 = bugStatus.value;
const status2 = resolution.value;
completeBtn = createButton(
"标记完成",
(btn) => {
var _a2;
btn.classList.add("custom-button");
btn.classList.add("plain-button");
(_a2 = duplicateSettings.parentNode) == null ? void 0 : _a2.insertBefore(btn, markDuplicateBox);
},
async () => {
resolutionSettings.classList.remove("bz_default_hidden");
resolution.value = RESOLUTION.FIXED;
bugStatus.value = BUG_STATUS.RESOLVED;
cancelBtn.classList.remove("hide");
completeBtn && completeBtn.classList.add("hide");
markDuplicateBox.classList.add("hide");
}
);
const cancelBtn = createButton(
"取消",
(btn) => {
var _a2;
btn.classList.add("plain-button");
btn.classList.add("hide");
(_a2 = duplicateSettings.parentNode) == null ? void 0 : _a2.appendChild(btn);
},
() => {
duplicateSettings.classList.add("bz_default_hidden");
markDuplicateBox.classList.remove("bz_default_hidden");
cancelBtn.classList.add("hide");
completeBtn && completeBtn.classList.remove("hide");
markDuplicateBox.classList.remove("hide");
bugStatus.value = status1;
if (status2) {
resolution.value = RESOLUTION.FIXED;
} else {
resolutionSettings.classList.add("bz_default_hidden");
}
}
);
if (markDuplicateBtn) {
markDuplicateBtn.classList.add("custom-button");
markDuplicateBtn.classList.add("plain-button");
markDuplicateBtn.innerText = "标记重复";
markDuplicateBtn.addEventListener("click", (e) => {
e.preventDefault();
duplicateSettings.classList.remove("bz_default_hidden");
markDuplicateBox.classList.add("bz_default_hidden");
cancelBtn.classList.remove("hide");
completeBtn && completeBtn.classList.add("hide");
});
}
}
if (commentBox) {
clearTextNode(commentBox);
const branchBox = document.createElement("div");
branchBox.style.setProperty("max-width", "610px");
branchBox.style.setProperty("display", "flex");
branchBox.style.setProperty("flex-wrap", "wrap");
if (getCustomBranches().length === 0) {
replaceCustomBranches([
{ title: ": " },
{ title: "develop" },
{ title: "v10.x" },
{ title: "v11.x" },
{ title: "custom_v11.0.1_huaweiDIS" },
{ title: "_R4" }
]);
}
getCustomBranches().forEach((item) => {
createButton(
item.title,
(btn) => {
btn.classList.add("custom-button");
btn.classList.add("plain-button");
btn.classList.add("mb-5");
branchBox.appendChild(btn);
},
() => {
commentTextArea.value = commentTextArea.value + item.title;
}
);
});
(_c = commentBox == null ? void 0 : commentBox.parentElement) == null ? void 0 : _c.insertBefore(branchBox, commentBox);
if (commentBoxLabel) {
commentBoxLabel.classList.add("hide");
}
if (commentTextArea) {
commentTextArea.style.setProperty("min-width", "719px");
commentTextArea.addEventListener("focus", () => {
commentTextArea.rows = 10;
});
}
}
if (attachmentDetails.length) {
const fileNames = $$("#attachment_table td[valign='top']:nth-child(0) b");
const fileTypeNodes = $$("#attachment_table td[valign='top']:nth-child(1) .bz_attach_extra_info");
attachmentDetails.forEach((attachment, index) => {
var _a2, _b2, _c2, _d2, _e;
attachment.classList.add("custom-button");
attachment.classList.add("plain-button");
attachment.style.margin = "6px 16px";
const url = (_a2 = attachment.href.split("&")) == null ? void 0 : _a2[0];
const fileType = ((_e = (_d2 = (_c2 = (_b2 = fileTypeNodes[index]) == null ? void 0 : _b2.innerText) == null ? void 0 : _c2.trim().match(/\(([^)]+)\)/)) == null ? void 0 : _d2[1].split(", ")) == null ? void 0 : _e[1]) ?? "";
const isViewType = fileType.includes("image") || fileType.includes("video") && !fileType.includes("wmv");
if (isViewType) {
attachment.innerText = "查看";
} else {
attachment.innerText = "下载";
}
attachment.addEventListener("click", (e) => {
var _a3;
e.preventDefault();
if (fileType.includes("image")) {
const loadingNode = createLoading();
const imageBodyNode = document.createElement("div");
imageBodyNode.classList.add("attachment-container");
imageBodyNode.classList.add("hide");
const imageNode = document.createElement("img");
imageNode.src = url;
imageNode.style = "width: 100%; height: auto;";
imageNode.addEventListener("load", () => {
imageBodyNode.classList.remove("hide");
imageBodyNode.classList.add("show");
loadingNode.classList.add("hide");
});
imageBodyNode.appendChild(imageNode);
const bodyNode = document.createElement("div");
bodyNode.appendChild(loadingNode);
bodyNode.appendChild(imageBodyNode);
createDialog({
title: "图片详情",
hideOk: true,
cancelText: "关闭",
body: bodyNode
});
} else if (fileType.includes("video") && !fileType.includes("wmv")) {
const loadingNode = createLoading();
const videoBodyNode = document.createElement("div");
videoBodyNode.classList.add("attachment-container");
videoBodyNode.classList.add("hide");
const videoNode = document.createElement("video");
videoNode.controls = true;
videoNode.autoplay = true;
videoNode.loop = true;
videoNode.style = "width: 100%; height: auto;";
const sourceNode = document.createElement("source");
sourceNode.src = url;
sourceNode.type = fileType;
sourceNode.style = "width: 100%; height: auto;";
videoNode.addEventListener("canplaythrough", () => {
videoBodyNode.classList.remove("hide");
videoBodyNode.classList.add("show");
loadingNode.classList.add("hide");
});
videoNode.appendChild(sourceNode);
videoBodyNode.appendChild(videoNode);
const bodyNode = document.createElement("div");
bodyNode.appendChild(loadingNode);
bodyNode.appendChild(videoBodyNode);
createDialog({
title: "视频详情",
hideOk: true,
cancelText: "关闭",
body: bodyNode
});
} else if (!isViewType) {
downloadResource(url, (_a3 = fileNames[index]) == null ? void 0 : _a3.innerText);
} else {
showErrorMessage("文件不存在,或者不支持从此处" + attachment.innerText);
}
});
});
}
const saveForm = (e, saveFormBtn) => {
e.preventDefault();
if (!getPageDetailControl("showSaveConfirmDialog")) {
onFormSubmit(saveFormBtn.form, true, bugId, bugTitleNode.innerText);
return;
}
const tips = [];
if (assignToSelect.value !== reporterEmail) {
tips.push("bug 没有指给报告人");
}
if (!commentTextArea.value) {
tips.push("bug 没有填写备注");
}
if (![BUG_STATUS.RESOLVED, BUG_STATUS.VERIFIED, BUG_STATUS.CLOSED].includes(bugStatus.value)) {
tips.push("bug 状态不是 RESOLVED, VERIFIED, CLOSED 其中一个");
}
if (tips.length) {
createDialog({
title: "请确认",
body: `
确定提交表单?
${tips.map((tip, index) => `${index + 1}. ${tip}`).join("")}
`,
style: "transform: translate(-50%, -70%)",
bodyStyle: "width: 500px;",
okText: "确定提交",
onOk: () => {
onFormSubmit(saveFormBtn.form, true, bugId, bugTitleNode.innerText);
}
});
return;
}
onFormSubmit(saveFormBtn.form, true, bugId, bugTitleNode.innerText);
};
if (saveFormBtn1) {
saveFormBtn1.classList.add("custom-button");
saveFormBtn1.value = "保存表单";
saveFormBtn1.title = "此功能可以通过页面顶部页面设置进行配置";
saveFormBtn1.addEventListener("click", (e) => saveForm(e, saveFormBtn1));
}
if (saveFormBtn2) {
saveFormBtn2.classList.add("custom-button");
saveFormBtn2.value = "保存表单";
saveFormBtn2.title = "此功能可以通过页面顶部页面设置进行配置";
saveFormBtn2.addEventListener("click", (e) => saveForm(e, saveFormBtn2));
saveFormBtn2.parentElement.style.setProperty("width", "170px");
saveFormBtn2.parentElement.style.setProperty("display", "flex");
saveFormBtn2.parentElement.style.setProperty("align-items", "center");
const quickSaveBtn = document.createElement("span");
quickSaveBtn.classList.add("custom-button");
quickSaveBtn.innerText = "一键填写";
quickSaveBtn.title = "自动获取 commit 信息,仅限开发人员使用";
quickSaveBtn.addEventListener("click", async (e) => {
const assignToTesterBtn = $("#assign_to_tester_btn");
assignToTesterBtn && assignToTesterBtn.click();
completeBtn && completeBtn.click();
const gitlabConfig = getGitlabConfig();
if (!gitlabConfig) {
showErrorMessage("请先配置 GitLab 信息");
gitlabConfigDialog();
return;
}
const closeMessage = showSuccessMessage("正在查询相关的 commit 记录...", 1e3 * 60 * 60);
const commits = await getBugCommitsFromProjects(bugId);
closeMessage();
if (!commits.length && getPageDetailControl("showCommitManualSelectDialog")) {
const closeMessage2 = showSuccessMessage("没有查找到与此 bug 相关的 commit,正在查询时间范围内的所有 commit...", 1e3 * 60 * 60);
const allCommits = await getAllCommits([2, 3, 24, 68]);
closeMessage2();
commitsManualSelectDialog(allCommits, commentTextArea);
return;
}
commentTextArea.value = "";
commits.forEach((commit) => {
commentTextArea.value += getProjectName(commit.projectId) + ": " + commit.targetBranch + ": " + commit.commitHash + " " + commit.commitMessage + "\n";
});
if (gitlabConfig.autoSaveForm) {
saveForm(e, saveFormBtn2);
}
});
saveFormBtn2.parentElement && ((_d = saveFormBtn2.parentElement) == null ? void 0 : _d.insertBefore(quickSaveBtn, saveFormBtn2));
}
if (navigationNode) {
const div = document.createElement("div");
div.classList.add("flex-justify-space-between");
const parentNode = navigationNode.parentNode;
parentNode.insertBefore(div, navigationNode.nextSibling);
div.appendChild(navigationNode);
const quickBottomBtn = document.createElement("a");
quickBottomBtn.href = "#footer";
quickBottomBtn.innerText = "快速沉底";
quickBottomBtn.classList.add("custom-button");
quickBottomBtn.classList.add("plain-button");
navigationNode.appendChild(quickBottomBtn);
const collectionNode = document.createElement("div");
collectionNode.classList.add("flex-center");
setCollectionIcon(collectionNode, bugIDNode.innerText);
div.appendChild(collectionNode);
const collectBugNode1 = document.getElementById("collect-bug");
if (collectBugNode1) {
const callback = (_, collectBugNode) => {
const { collectedBugs, hasCollected } = getCollectInfo(bugIDNode.innerText);
let newBugs;
if (!hasCollected) {
newBugs = {
list: [
...collectedBugs,
{
id: bugIDNode.innerText,
title: bugTitleNode.innerText,
url: window.location.href
}
]
};
if (collectBugNode.dataset.type !== "no-collected") {
showErrorMessage("数据与页面状态不一致,页面刷新后重试");
setTimeout(() => {
window.location.reload();
}, 1e3);
return;
}
showSuccessMessage("收藏成功");
} else {
newBugs = {
list: collectedBugs.length > 0 && collectedBugs.filter((bug) => bug.id !== bugIDNode.innerText)
};
if (collectBugNode.dataset.type !== "collected") {
showErrorMessage("数据与页面状态不一致,页面刷新后重试");
setTimeout(() => {
window.location.reload();
}, 1e3);
return;
}
showSuccessMessage("已取消收藏");
}
localStorage.setItem(STORAGE_KEY_MAP.COLLECTED_BUGS, JSON.stringify(newBugs));
setCollectionIcon(collectionNode, bugIDNode.innerText);
const collectBugNode2 = document.getElementById("collect-bug");
if (collectBugNode2) {
collectBugNode2.addEventListener("click", (e) => callback(e, collectBugNode2));
}
};
collectBugNode1.addEventListener("click", (e) => callback(e, collectBugNode1));
}
}
if (attachmentNode) {
attachmentNode.classList.add("custom-button");
attachmentNode.innerText = "添加附件";
attachmentNode.title = "此功能可以通过页面顶部页面设置进行配置";
if (getPageDetailControl("showAttechmentDialog")) {
attachmentNode.addEventListener("click", (e) => {
e.preventDefault();
createDialog({
title: "上传附件",
okText: "关闭弹窗 & 刷新页面",
cancelText: "关闭",
bodyStyle: "width: 60vw; height: 70vh;",
body: `
备注:点击 Submit 按钮上传,上传后点击右下角关闭并刷新按钮刷新整个页面,查看上传结果
`,
onMount: () => {
iframeCallback("attachment-iframe", (contentDocument) => {
const header = $("#header", contentDocument);
const footer = $("#footer", contentDocument);
if (header) {
header.remove();
}
if (footer) {
footer.remove();
}
});
},
onOk: () => {
window.location.reload();
}
});
});
}
}
if (attachmentViewAll) {
attachmentViewAll.remove();
}
if (table2AllRows == null ? void 0 : table2AllRows.length) {
table2AllRows.forEach((row) => {
var _a2;
if (row.firstElementChild && row.firstElementChild.classList.contains("bz_hidden_field")) {
row.firstElementChild.classList.remove("bz_hidden_field");
}
if (((_a2 = row.firstElementChild) == null ? void 0 : _a2.nextElementSibling) && row.firstElementChild.nextElementSibling.classList.contains("bz_hidden_field")) {
row.firstElementChild.nextElementSibling.classList.remove("bz_hidden_field");
}
});
}
if (navigationABtns.length) {
navigationABtns.forEach((node) => {
navBtnAddStyle(node);
});
}
if (navigationFontBtns.length) {
navigationFontBtns.forEach((node) => {
navBtnAddStyle(node, true);
});
}
showHideFormItemsByData();
if (commentNodes.length) {
commentNodes.forEach((node) => {
switchCommitHash2ALink(node, (e, hash, projectName) => {
if (getPageDetailControl("directOpenGitlabWhenHashRecognized") && projectName) {
openGitlabByHash(hash, projectName);
return;
}
const opts = [
{
label: "复制 hash",
key: "copy"
},
{
label: "从 bi 打开",
key: "bi"
},
{
label: "从 core 打开",
key: "core"
},
{
label: "从 pptr 打开",
key: "PPTR"
},
{
label: "从 workbook 打开",
key: "yh-plugin-workbook"
}
];
const appIns = moreAction(opts, (key) => {
if (key === "copy") {
copyText(hash);
return;
}
openGitlabByHash(hash, key);
});
invokeFromVueAppIns(appIns, "showDropdown", { posX: e.clientX, posY: e.clientY });
});
});
}
viewImageFullScreen(firstComment);
};
const renderBugDetailPage = () => {
if (PATHNAME === PathNameEnum.BUG_DETAIL) {
renderBugDetail();
assignToList();
newCCList();
featureList();
componentList();
versionList();
}
};
const getChineseName = (persons, string) => {
if (persons) {
if (string.includes("@")) {
const name = string.split("@")[0];
return persons[name];
}
}
return string;
};
const renderBugHistory = () => {
const table = $("#bugzilla-body table");
const tds = $$("#bugzilla-body table td");
const bugLinks = $$("#bugzilla-body .bz_bug_link");
if (table) {
table.style = "border-collapse: collapse";
const persons = getPersonMap();
if (Array.isArray(tds)) {
tds.forEach((td) => {
td.innerText = getChineseName(persons, td.innerText);
});
}
}
if (bugLinks.length > 0) {
bugLinks.forEach((link) => {
link.classList.add("hide");
});
}
};
const renderBugHistoryPage = () => {
if (PATHNAME === PathNameEnum.BUG_HISTORY) {
renderBugHistory();
}
};
const getCity = () => {
return localStorage.getItem(STORAGE_KEY_MAP.CITY) ?? "北京";
};
const setCity = (city) => {
if (!city) {
showErrorMessage("设置城市的值不能为空");
return;
}
return localStorage.setItem(STORAGE_KEY_MAP.CITY, city);
};
async function getWeatherURL(options) {
const { publicKey, privateKey, location } = options;
if (!publicKey || !privateKey || !location) {
throw new Error("公钥、私钥、城市location不能为空");
}
const params = {
ts: Math.floor(Date.now() / 1e3).toString(),
ttl: options.ttl || 1800,
uid: publicKey
};
const sortedKeys = Object.keys(params).sort();
const paramString = sortedKeys.map((key) => `${key}=${params[key]}`).join("&");
const hmac = CryptoJS.HmacSHA1(paramString, privateKey);
const base64Signature = hmac.toString(CryptoJS.enc.Base64);
const sig = encodeURIComponent(base64Signature);
const apiType = "now.json";
const fullParams = `${paramString}&sig=${sig}&location=${encodeURIComponent(location)}`;
return `https://api.seniverse.com/v3/weather/${apiType}?${fullParams}&language=zh-Hans&unit=c`;
}
const API_OPTIONS = {
publicKey: "Po_TCkQPEmOGYBCye",
privateKey: "SyHEWyXh1IRy-0Agl",
apiType: "now",
ttl: 1800
};
const getWeather = async () => {
try {
const city = getCity();
const url = await getWeatherURL({
publicKey: API_OPTIONS.publicKey,
privateKey: API_OPTIONS.privateKey,
location: city,
apiType: API_OPTIONS.apiType,
ttl: API_OPTIONS.ttl
});
const res = await fetch(url);
const data = await res.json();
return data;
} catch (err) {
console.error("天气API错误:", err);
return null;
}
};
const sleep = (s) => new Promise((resolve) => setTimeout(resolve, s * 1e3));
const renderQuip = () => {
const quip = $(".bz_quip");
if (quip) {
const quipTypes = [
{
url: "http://api.qemao.com/api/yulu/?type=1",
type: "毒鸡汤语录"
},
{
url: "http://api.qemao.com/api/yulu/?type=2",
type: "祖安语录"
},
{
url: "http://api.qemao.com/api/yulu/?type=3",
type: "社会语录"
}
];
localStorage.setItem(STORAGE_KEY_MAP.QUIP_TYPE, "0");
const getText = async (urlObj) => {
try {
GM_xmlhttpRequest({
method: "GET",
url: urlObj.url,
onload: function(res) {
if (res && res.status === 200) {
const text = res.responseText;
const quipType2 = parseInt(localStorage.getItem(STORAGE_KEY_MAP.QUIP_TYPE) ?? "0");
const quipHtml = `
${text} (点我刷新)
${quipTypes.map(
(quip2, index) => `
`
).join("")}
`;
quip.innerHTML = quipHtml;
const quipText = $("#quip-text");
const radios = $$("input[type='radio'][name='quipType']", quip);
radios.forEach((radio) => {
if (radio.value === quipType2.toString()) {
radio.checked = true;
}
radio.addEventListener("change", () => {
const quipType3 = radio.value;
localStorage.setItem(STORAGE_KEY_MAP.QUIP_TYPE, quipType3);
getText(quipTypes[+quipType3]);
});
});
if (quipText) {
quipText.addEventListener("click", () => {
getText(quipTypes[quipType2]);
});
}
}
}
});
} catch (error) {
console.error(error);
}
};
const quipType = parseInt(localStorage.getItem(STORAGE_KEY_MAP.QUIP_TYPE) ?? "0");
getText(quipTypes[quipType]);
}
};
const renderWeather = () => {
const queryInfo = $(".bz_query_timestamp");
if (queryInfo) {
queryInfo.innerHTML = "加载中...";
const settingCity = () => {
const input = document.createElement("input");
input.style.setProperty("width", "100%");
input.value = getCity();
createDialog({
title: "设置城市",
bodyStyle: "width: 400px; height: 60px",
body: input,
onOk: async (closeDialog) => {
const value = input.value;
if (value) {
setCity(value);
showSuccessMessage("正在验证当前城市是否存在", 2e3);
const res = await getWeather();
await sleep(2);
if (res && res.status_code && res.status_code.includes("AP")) {
showErrorMessage("当前城市不存在,为你设置为默认城市:北京", 3e3);
input.value = "北京";
setCity(input.value);
return;
}
closeDialog();
getWeatherUI();
} else if (!value) {
showErrorMessage("请输入城市名称");
}
}
});
};
const getWeatherUI = async () => {
try {
await loadScriptByGM(CDNScriptURLEnum.CRYPTO_JS);
const res = await getWeather();
if (!res) {
showErrorMessage("获取天气失败");
return;
}
const now = res.results[0].now;
if (!now) {
return;
}
const divider = `|`;
const weatherArr = [
`${getCity()}
`,
getDayOfWeek("zhou"),
now.text,
now.temperature + "度"
];
queryInfo.innerHTML = weatherArr.map((it, index) => {
if (index === weatherArr.length - 1) {
return it;
} else {
return it + divider;
}
}).join("");
const refreshBtn = document.createElement("span");
refreshBtn.title = "刷新天气";
refreshBtn.style.display = "inline-block";
refreshBtn.style.marginLeft = "10px";
refreshBtn.style.transform = "translateY(2px)";
refreshBtn.innerHTML = ``;
refreshBtn.classList.add("cursor-pointer");
refreshBtn.addEventListener("click", async () => {
refreshBtn.firstElementChild.classList.add("self-rotate");
await sleep(0.7);
await getWeatherUI();
showSuccessMessage("刷新成功");
});
queryInfo.appendChild(refreshBtn);
const settingCityBtn = $("#setting-city");
if (settingCityBtn) {
settingCityBtn.addEventListener("click", settingCity);
}
} catch (error) {
console.error(error);
}
};
getWeatherUI();
}
};
const renderBugList = () => {
const longFormat = $("#long_format");
const xml = $("#xml");
const timeSummary = $("#timesummary");
const remember = $("#remember");
const bzIdColumns = $$(".bz_id_column a");
const bzShortDescColumns = $$(".bz_short_desc_column a");
const buglistRows = $$(".bz_buglist .bz_bugitem");
if (longFormat) {
longFormat.classList.add("custom-button");
longFormat.classList.add("plain-button");
longFormat.style.marginLeft = "0";
}
if (xml) {
xml.classList.add("custom-button");
xml.classList.add("plain-button");
xml.style.marginLeft = "0";
}
if (timeSummary) {
timeSummary.classList.add("custom-button");
timeSummary.classList.add("plain-button");
timeSummary.style.marginLeft = "0";
}
if (remember) {
remember.classList.add("custom-button");
remember.classList.add("plain-button");
remember.style.marginLeft = "0";
}
if (bzIdColumns) {
bzIdColumns.forEach((node) => {
const td = node.parentNode;
td.style.paddingLeft = "0px";
td.style.width = "100px";
node.classList.add("custom-button");
node.classList.add("plain-button");
node.addEventListener("click", (e) => {
e.preventDefault();
window.open(node.href, "_blank");
});
});
}
if (bzShortDescColumns) {
bzShortDescColumns.forEach((node) => {
node.addEventListener("click", (e) => {
e.preventDefault();
window.open(node.href, "_blank");
});
});
}
if (buglistRows.length) {
const persons = getPersonMap();
buglistRows.forEach((node, index) => {
const children = Array.from(node.children);
children.forEach((child) => {
const isSpan = child.firstElementChild && child.firstElementChild.tagName === "SPAN";
if (isEmail(child.innerText)) {
child.innerText = getChineseName(persons, child.innerText);
} else if (isSpan) {
const span = child.firstElementChild;
if (span.title && isEmail(span.title)) {
span.innerText = getChineseName(persons, span.title);
}
}
});
const bugId = bzIdColumns[index].innerText;
const bugTextNode = $(".bz_short_desc_column a", node);
const bugText = bugTextNode.innerText;
const bugUrl = bugTextNode.href;
const td = document.createElement("td");
td.style.minWidth = "90px";
showReportBtn(td, bugId, bugText, bugUrl);
const completeBtn = showResolvedMarkBtn(td, bugId);
showCollectionBtn(td, bugId, bugText, bugUrl);
const widthMap = new Map([
[1, 90],
[2, 180],
[3, 270]
]);
td.style.width = `${widthMap.get(td.children.length) ?? 100}px`;
node.appendChild(td);
if (getListPageActionBtnShow(ACTION_BTNS.RESOLVED_MARK)) {
const completedBugsStr = localStorage.getItem(STORAGE_KEY_MAP.COMPLETED_BUGS) ?? "";
const completedBugs = completedBugsStr.split(";").filter((p) => p);
if (completeBtn && completedBugs.includes(node.id)) {
completeBtn.classList.add("plain-button");
node.style.setProperty("background-color", "#c7c7c7ff");
}
}
});
}
renderQuip();
renderWeather();
};
const renderBugListPage = () => {
if (PATHNAME === PathNameEnum.BUG_LIST) {
renderBugList();
}
};
const ccList = () => {
const persons = getPersonMap();
const ccSelect = $("#cc");
if (!ccSelect) {
return;
}
const ccSelectOptions = $$("#cc > option");
const div = document.createElement("div");
div.id = "cc_list_vue_app";
ccSelect.parentNode.insertBefore(div, ccSelect);
ccSelect.classList.add("bz_default_hidden");
ccSelectOptions.forEach((node) => {
const strMatch = node.innerText.match(/<([^]+)@(yonghongtech|test|sina).(com|cn)>/);
const englishName = strMatch ? strMatch[1] : "";
node.innerText = englishName && persons[englishName] ? persons[englishName] + " - " + node.innerText.replace("-", "").replace(persons[englishName], "") : node.innerText;
});
const { createApp, ref, reactive } = Vue;
const app = createApp({
template: `
`,
setup() {
const selectedValue = ref(ccSelect.value);
const options = reactive(
ccSelectOptions.map((option) => {
return {
label: option.innerText,
value: option.value
};
})
);
return {
selectedValue,
options,
handleUpdateValue(value) {
ccSelect.value = value;
}
};
}
});
app.use(naive);
return app.mount("#cc_list_vue_app");
};
const updateQuickSummary = (text, isAdd, isShowMessage = true) => {
let quickSummary = getQuickSummary();
if (isAdd) {
if (quickSummary.some((item) => item.title === text)) {
if (isShowMessage) {
showErrorMessage("快捷短语已存在");
}
return;
}
quickSummary.push({ title: text });
if (isShowMessage) {
showSuccessMessage("添加成功");
}
} else {
quickSummary = quickSummary.filter((item) => item.title !== text);
if (isShowMessage) {
showSuccessMessage("删除成功");
}
}
localStorage.setItem(STORAGE_KEY_MAP.QUICK_SUMMARY, JSON.stringify(quickSummary));
};
const getQuickSummary = () => {
return JSON.parse(localStorage.getItem(STORAGE_KEY_MAP.QUICK_SUMMARY) ?? "[]");
};
const replaceQuickSummary = (quickSummary) => {
localStorage.setItem(STORAGE_KEY_MAP.QUICK_SUMMARY, JSON.stringify(quickSummary));
};
const quickSummaryDialog = () => {
let appIns = null;
const appId = "quick_summary_vue_app";
createDialog({
title: "自定义快捷短语",
cancelText: "关闭",
okText: "刷新页面",
bodyStyle: "width: 60vw; height: 60vh;",
body: `
`,
onOk: () => {
window.location.reload();
},
onMount: () => {
const quickSummary = getQuickSummary();
const { createApp, ref, h } = Vue;
const app = createApp({
template: `
搜索:
新增
`,
setup() {
const searchValue = ref("");
const quickSummaryText = ref("");
const data = ref(quickSummary);
const columns = ref([
{
title: "名称",
dataIndex: "title",
key: "title",
width: "calc(60vw - 380px)",
ellipsis: {
tooltip: true
}
},
{
title: "排序",
dataIndex: "sort",
key: "sort",
width: 200,
render: (_, index) => {
return h(
naive.NSpace,
{
horizontal: true
},
{
default: () => [
h(naive.NButton, {
strong: true,
tertiary: true,
size: "small",
textContent: "↑",
disabled: index === 0,
onClick: () => {
data.value = moveUp(data.value, index);
replaceQuickSummary(data.value);
}
}),
h(naive.NButton, {
strong: true,
tertiary: true,
size: "small",
textContent: "↓",
disabled: index === data.value.length - 1,
onClick: () => {
data.value = moveDown(data.value, index);
replaceQuickSummary(data.value);
}
})
]
}
);
}
},
{
title: "操作",
key: "actions",
width: 180,
render: (row) => {
return h(
naive.NSpace,
{
horizontal: true
},
{
default: () => [
h(naive.NButton, {
strong: true,
tertiary: true,
size: "small",
textContent: "删除",
onClick: () => {
data.value = data.value.filter((item) => item.title !== row.title);
updateQuickSummary(row.title, false);
}
})
]
}
);
}
}
]);
const onSearch = debounce((value) => {
if (value) {
data.value = data.value.filter((item) => item.title.includes(value));
} else {
data.value = getQuickSummary();
}
}, 500);
const addQuickSummary = debounce(() => {
if (quickSummaryText.value) {
data.value = [...data.value, { title: quickSummaryText.value }];
updateQuickSummary(quickSummaryText.value, true);
quickSummaryText.value = "";
}
}, 500);
return {
searchValue,
quickSummaryText,
data,
columns,
onSearch,
addQuickSummary
};
}
});
app.use(naive);
appIns = app.mount("#" + appId);
}
});
return appIns;
};
const countLineBreaks = (str) => {
if (!str) {
return 0;
}
return (str.match(/[\n\r]/g) || []).length;
};
const validateSummary = (value) => {
const errorComponents = $$(".validation_error_text");
if (value) {
errorComponents.forEach((error) => {
if (error.innerText === "You must enter a Summary for this bug.") {
error.classList.add("bz_default_hidden");
}
});
} else {
errorComponents.forEach((error) => {
if (error.innerText === "You must enter a Summary for this bug.") {
error.classList.remove("bz_default_hidden");
}
});
}
};
const renderBugReport = () => {
var _a, _b, _c, _d, _e, _f;
const newBugForm = $("#Create");
const allTableCells = newBugForm ? $$("table tr td", newBugForm) : null;
const descriptionTextArea = $("#comment");
const versionLabel = $("#field_label_version");
const guessNote = $("#os_guess_note");
const commit = $("#commit");
const shortDesc = $("#short_desc");
const attachFalseInput = $("#attachment_false input");
const attachTrueInput = $("#attachment_true input");
const attatchData = $("#attachment_true .attachment_entry input");
const priority = $("#field_label_priority");
const topTip = $("form table tr");
const possibleDuplicatesContainer = $("#possible_duplicates_container");
const assignedToHelpLink = $("#field_label_assigned_to .field_help_link");
if (descriptionTextArea) {
descriptionTextArea.onfocus = null;
descriptionTextArea.addEventListener("focus", (e) => {
e.preventDefault();
e.stopPropagation();
});
const col = descriptionTextArea.parentElement;
for (let i = 0; i < col.children.length; i++) {
const child = col.children[i];
if (child.tagName === "BR") {
child.remove();
}
}
}
if (Array.isArray(allTableCells)) {
allTableCells.forEach((cell) => {
var _a2;
const textContent = ((_a2 = cell == null ? void 0 : cell.textContent) == null ? void 0 : _a2.trim().replace(/\s+/g, "")) || "";
if ((cell.colSpan === 4 || cell.colSpan === 3) && cell.childElementCount === 0 && textContent === "") {
cell.remove();
}
});
}
if (versionLabel) {
versionLabel.rowSpan = 1;
versionLabel.nextElementSibling.rowSpan = 1;
}
if (guessNote) {
((_a = guessNote.parentNode) == null ? void 0 : _a.firstElementChild).colSpan = 1;
guessNote.firstElementChild.innerText = "已经预填部分字段,请自行检查正确与否";
}
if (commit) {
commit.classList.add("custom-button");
commit.classList.add("margin-0");
commit.value = "提交 bug";
commit.addEventListener("mouseup", () => {
const timer = setTimeout(() => {
const errorComponents = $$(".validation_error_text");
errorComponents.forEach((error) => {
if (error.innerText === "You must enter a Summary for this bug.") {
error.style.setProperty("position", "absolute");
error.style.setProperty("top", "8px");
error.style.setProperty("right", "160px");
}
});
clearTimeout(timer);
}, 50);
});
}
if (shortDesc) {
const quickSummaryBox = document.createElement("tr");
const quickSummaryBoxTitle = document.createElement("th");
const quickSummaryBoxCell = document.createElement("td");
quickSummaryBoxCell.colSpan = 3;
quickSummaryBox.appendChild(quickSummaryBoxTitle);
quickSummaryBox.appendChild(quickSummaryBoxCell);
quickSummaryBoxCell.style.setProperty("width", "650px");
quickSummaryBoxCell.style.setProperty("display", "flex");
quickSummaryBoxCell.style.setProperty("flex-wrap", "wrap");
if (getQuickSummary().length === 0) {
replaceQuickSummary([{ title: "" }]);
}
getQuickSummary().forEach((item) => {
createButton(
item.title,
(btn) => {
btn.classList.add("custom-button");
btn.classList.add("plain-button");
btn.classList.add("margin-0");
btn.classList.add("mr-5");
btn.classList.add("mb-5");
quickSummaryBoxCell.appendChild(btn);
},
() => {
const descText = shortDesc.value + item.title;
shortDesc.value = descText;
validateSummary(descText);
}
);
});
(_b = possibleDuplicatesContainer == null ? void 0 : possibleDuplicatesContainer.parentElement) == null ? void 0 : _b.insertBefore(quickSummaryBox, possibleDuplicatesContainer);
shortDesc.parentElement.style.setProperty("display", "flex");
shortDesc.parentElement.style.setProperty("align-items", "center");
shortDesc.parentElement.style.setProperty("width", "800px");
shortDesc.parentElement.style.setProperty("position", "relative");
shortDesc.addEventListener("input", (e) => {
var _a2;
return validateSummary((_a2 = e == null ? void 0 : e.target) == null ? void 0 : _a2.value);
});
const div = document.createElement("div");
div.classList.add("custom-button");
div.innerText = "自定义快捷短语";
div.addEventListener("click", () => {
quickSummaryDialog();
});
shortDesc.parentElement.insertBefore(div, shortDesc.nextElementSibling);
}
const btnGroup = document.createElement("div");
btnGroup.classList.add("mt-5");
btnGroup.style.setProperty("display", "flex");
btnGroup.style.setProperty("justify-content", "flex-start");
btnGroup.style.setProperty("align-items", "center");
(descriptionTextArea == null ? void 0 : descriptionTextArea.parentElement) && descriptionTextArea.parentElement.appendChild(btnGroup);
const switchBtn = createButton(
"切换为普通输入框",
(btn) => {
btn.classList.add("custom-button");
btn.classList.add("margin-0");
btn.classList.add("mr-5");
btn.title = "切换为普通输入框后,不支持切回富文本";
if (descriptionTextArea == null ? void 0 : descriptionTextArea.parentElement) {
btnGroup.appendChild(btn);
}
},
() => {
switchBtn.remove();
const descriptionCKEEditor = $("#cke_comment");
if (descriptionCKEEditor) {
descriptionCKEEditor.style.setProperty("display", "none");
}
descriptionTextArea == null ? void 0 : descriptionTextArea.style.setProperty("display", "block");
descriptionTextArea == null ? void 0 : descriptionTextArea.style.setProperty("visibility", "visible");
if (descriptionTextArea) {
descriptionTextArea.value = localStorage.getItem(STORAGE_KEY_MAP.NEW_BUG_COMMENT_TEMPLATE) || COMMENT_DEFAULT_TEMPLATE_1;
}
if (descriptionTextArea) {
descriptionTextArea.rows = countLineBreaks((descriptionTextArea == null ? void 0 : descriptionTextArea.value) || "") + 2;
}
createButton(
"将当前描述内容设置为默认模板",
(btn) => {
btn.classList.add("custom-button");
btn.classList.add("margin-0");
btn.classList.add("mr-5");
btn.classList.add("plain-button");
if (descriptionTextArea == null ? void 0 : descriptionTextArea.parentElement) {
btnGroup.appendChild(btn);
}
},
() => {
if (!(descriptionTextArea == null ? void 0 : descriptionTextArea.value)) {
showErrorMessage("请输入模板内容");
return;
}
localStorage.setItem(STORAGE_KEY_MAP.NEW_BUG_COMMENT_TEMPLATE, (descriptionTextArea == null ? void 0 : descriptionTextArea.value) || "");
showSuccessMessage("模板已更新");
}
);
createButton(
"使用模板1",
(btn) => {
btn.classList.add("custom-button");
btn.classList.add("plain-button");
btn.title = COMMENT_DEFAULT_TEMPLATE_1;
if (descriptionTextArea == null ? void 0 : descriptionTextArea.parentElement) {
btnGroup.appendChild(btn);
}
},
() => {
if (descriptionTextArea) {
descriptionTextArea.rows = 24;
descriptionTextArea.value = COMMENT_DEFAULT_TEMPLATE_1;
}
}
);
createButton(
"使用模板2",
(btn) => {
btn.classList.add("custom-button");
btn.classList.add("plain-button");
btn.title = COMMENT_DEFAULT_TEMPLATE_2;
if (descriptionTextArea == null ? void 0 : descriptionTextArea.parentElement) {
btnGroup.appendChild(btn);
}
},
() => {
if (descriptionTextArea) {
descriptionTextArea.rows = 19;
descriptionTextArea.value = COMMENT_DEFAULT_TEMPLATE_2;
}
}
);
}
);
if (attachFalseInput && attachTrueInput && attatchData) {
attachFalseInput.value = "上传附件";
attachTrueInput.value = "取消上传";
attachFalseInput.classList.add("custom-button");
attachFalseInput.classList.add("margin-0");
attachFalseInput.classList.add("plain-button");
attachTrueInput.classList.add("custom-button");
attachTrueInput.classList.add("margin-0");
attachTrueInput.classList.add("plain-button");
const uploadFileBtn = document.createElement("span");
const fileName = document.createElement("span");
uploadFileBtn.classList.add("custom-button");
uploadFileBtn.classList.add("margin-0");
uploadFileBtn.classList.add("plain-button");
uploadFileBtn.innerText = "重新上传";
fileName.classList.add("bug-new_filename");
attatchData.classList.add("bz_default_hidden");
(_c = attatchData.parentNode) == null ? void 0 : _c.insertBefore(fileName, attatchData.nextElementSibling);
(_d = attatchData.parentNode) == null ? void 0 : _d.insertBefore(uploadFileBtn, attatchData.nextElementSibling);
attachFalseInput.addEventListener("click", () => {
attatchData.click();
});
uploadFileBtn.addEventListener("click", () => {
attatchData.click();
});
attatchData.addEventListener("change", (e) => {
const pathArr = e.target.value.split("\\");
const sizeM = e.target.files[0].size / 1024;
fileName.innerText = "文件名:" + pathArr[pathArr.length - 1] + " 大小:" + sizeM.toFixed(2) + "kb";
});
}
if (topTip) {
topTip.remove();
}
if (priority) {
(_f = (_e = priority.parentElement) == null ? void 0 : _e.firstElementChild) == null ? void 0 : _f.remove();
}
if (assignedToHelpLink) {
assignedToHelpLink.style.setProperty("color", "var(--primaryColor)");
}
};
const renderBugReportEntry = () => {
const products = $$("table th[valign='top'] a");
const productDescs = $$("table td[valign='top']");
if (products.length) {
products.forEach((p) => {
p.classList.add("custom-button");
p.addEventListener("click", (e) => {
e.preventDefault();
window.open(p.href, "_blank");
});
});
}
if (productDescs.length) {
productDescs.forEach((pd) => {
pd.vAlign = "center";
});
}
};
const renderBugReportPage = () => {
if (PATHNAME === PathNameEnum.BUG_NEW) {
if (isBugReportPage()) {
renderBugReport();
componentList();
assignToList();
versionList();
featureList();
ccList();
}
if (isBugReportEntryPage()) {
renderBugReportEntry();
}
}
};
const renderBugReportEntryPage = () => {
if (PATHNAME === PathNameEnum.BUG_NEW_ENTRY) {
renderBugReportEntry();
}
};
const renderBugProcess = () => {
const bugLink = $("#bugzilla-body .bz_bug_link");
if (bugLink) {
bugLink.innerText = "返回 " + bugLink.innerText;
bugLink.classList.add("custom-button");
}
};
const renderBugProcessPage = () => {
if (PATHNAME === PathNameEnum.BUG_PROCESS) {
renderBugProcess();
}
};
const countDownCallback = (callback, count) => {
let timer = null;
timer = setInterval(() => {
count--;
if (count <= 0) {
preventBoom(callback);
timer && clearInterval(timer);
}
}, 1e3);
return () => clearInterval(timer);
};
try {
async function setup() {
const clearTimer = countDownCallback(() => {
showSuccessMessage("加载外部资源时间过长,请检查网络连接或 VPN 状态", 5e3);
}, 5);
await loadScriptByGM(CDNScriptURLEnum.VUE);
await loadScriptByGM(CDNScriptURLEnum.NAIVE_UI);
clearTimer();
renderBugCommon();
renderBugListPage();
renderBugDetailPage();
renderBugReportPage();
renderBugReportEntryPage();
renderBugAttachmentPage();
renderBugHistoryPage();
renderBugProcessPage();
}
setup();
} catch (error) {
console.error(error);
}
})();