// ==UserScript==
// @name Bugzilla Script
// @namespace xiwenge
// @version 0.63.0
// @description 美化增强 Bugzilla 页面
// @author xiwenge
// @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_xmlhttpRequest
// @grant GM_setClipboard
// @run-at document-end
// ==/UserScript==
(function () {
"use strict";
const style = `
/**
* 全局样式
* 在这里书写的样式会被编译为 style/index.ts,成为一个 js 模块
*/
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: 0px;
z-index: 1999;
}
#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;
inset: 0;
opacity: 1;
transition-duration: 0.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;
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: #ffffff !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: rgba(0, 0, 0, 0.25) !important;
background: rgba(0, 0, 0, 0.04) !important;
box-shadow: none !important;
pointer-events: none !important;
}
.disabled-button:hover {
cursor: not-allowed !important;
border-color: #d9d9d9 !important;
color: rgba(0, 0, 0, 0.25) !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 {
height: 28px;
}
#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 {
display: none;
}
#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: #ffffff;
border-radius: 4px;
transition: opacity 0.5s ease-in-out, top 0.5s ease-in-out;
animation: message-fadein 0.5s ease-in-out forwards;
box-shadow: 0 0 6px 0 rgba(0, 0, 0, 0.2);
}
.global-message_text {
margin-left: 8px;
font-size: 14px;
}
@keyframes message-fadein {
0% {
opacity: 0.5;
top: 10px;
}
100% {
opacity: 1;
top: 30px;
}
}
@keyframes dialog-fadein {
0% {
opacity: 0.5;
top: 46%;
}
100% {
opacity: 1;
top: 50%;
}
}
@keyframes loading {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.global-dialog {
height: fit-content;
max-width: 100vw;
max-height: 100vh;
z-index: 9999;
position: absolute;
left: 50%;
transform: translate(-50%, -50%);
background-color: #ffffff;
border-radius: 4px;
transition: opacity 0.5s ease-in-out, top 0.5s ease-in-out;
animation: dialog-fadein 0.5s ease-in-out forwards;
}
.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: rgba(0, 0, 0, 0.5);
}
.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;
}
.hide {
display: none;
}
.cursor-pointer:hover {
cursor: pointer;
}
.text-underline {
text-decoration: underline;
}
.font-size-16px {
font-size: 16px;
}
.font-bold {
font-weight: bold;
}
.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: bold;
transition: all 0.3s ease-in-out;
}
.link-title:hover {
color: var(--primaryColor) !important;
text-decoration: unset !important;
}
.separator {
margin: 0 6px 0 4px;
color: #cccccc;
}
.links .form a[title="Quicksearch Help"] {
margin-left: 6px;
}
#attachment_table {
border: 1px solid #d9d9d9;
}
#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;
}
.bz_short_desc_column a {
color: #595959;
font-weight: bold;
}
#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: bold;
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(0.5px, 1px);
}
#setting-city {
display: inline-block;
color: var(--primaryColor);
}
#setting-city:hover {
cursor: pointer;
}
#setting-city svg {
transition: all 0.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: grey;
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 {
user-select: none;
}
.clear-br-label:hover {
cursor: pointer;
color: var(--primaryColorHover);
}
`;
var MessageTypeEnum = /* @__PURE__ */ ((MessageTypeEnum2) => {
MessageTypeEnum2["SUCCESS"] = "success";
MessageTypeEnum2["ERROR"] = "error";
return MessageTypeEnum2;
})(MessageTypeEnum || {});
const applyCallBack = (fun, ...args) => {
if (fun && typeof fun === "function") {
return fun(...args);
}
};
var CDNScriptURLEnum = /* @__PURE__ */ ((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 createDialog = ({
title = "",
body,
footer,
maskTransparent = false,
okText = "确定",
cancelText = "取消",
onOk,
onCancel,
hideOk = false,
hideCancel = false,
className = "",
bodyClassName = "",
style: style2 = "",
bodyStyle = "",
onMount = () => {},
onDestroy = () => {},
}) => {
let storeDialogWidth = 0;
let storeDialogHeight = 0;
let isDialogFullScreen = void 0;
const existDialogNodes = document.querySelectorAll(".global-dialog");
const length = existDialogNodes.length;
const zIndex = 9999 + 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.width = "calc(100% - 64px)";
headerTitle.appendChild(titleNode);
titleNode.style.transform = "translateX(-32px)";
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);
const animation = dialogNode.animate(
[
{ opacity: 1, top: "50%" },
{ opacity: 0, top: "46%" },
],
{
duration: 500,
easing: "ease-in-out",
fill: "forwards",
},
);
animation.onfinish = () => {
animation.cancel();
document.body.removeChild(maskNode);
const dialogs = document.querySelectorAll(".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) {
isDialogFullScreen = false;
dialogNode.style.width = `${Math.ceil(storeDialogWidth)}px`;
dialogNode.style.height = `${Math.ceil(storeDialogHeight)}px`;
}
});
fullScreenBtn.addEventListener("click", () => {
if (!isDialogFullScreen) {
isDialogFullScreen = true;
dialogNode.style.width = "100%";
dialogNode.style.height = "99.6%";
dialogNode.style.transform = "translate(-50%, -50.4%)";
dialogBody.style.width = "100%";
dialogBody.style.height = "100%";
}
});
headerBtn.appendChild(closeBtn);
headerBtn.appendChild(exitFullScreenBtn);
headerBtn.appendChild(fullScreenBtn);
header.appendChild(headerBtn);
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 (style2) {
dialogNode.style = style2;
}
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", () => {
applyCallBack(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 applyCallBack(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 escEvent = (e) => {
if (e.key === "Escape") {
closeDialog();
}
};
const enterEvent = (e) => {
if (e.key === "Enter") {
applyCallBack(onOk, closeDialog);
}
};
document.addEventListener("keydown", enterEvent);
document.addEventListener("keydown", escEvent);
onMount();
};
const createLoading = (style2 = "width: 400px; height: 225px;") => {
const loadingNode = document.createElement("div");
loadingNode.classList.add("global-loading");
loadingNode.style = style2;
return loadingNode;
};
const loadScriptByGM = (url) => {
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: "GET",
url,
onload: (res) => {
const script = document.createElement("script");
script.textContent = res.responseText;
document.head.appendChild(script);
resolve(true);
},
onerror: reject,
});
});
};
const createEditorDialog = (dialogProps = {}) => {
return new Promise(async (resolve) => {
const loadingNode = createLoading("width: 100%; height: 100%");
const bodyNode = document.createElement("div");
bodyNode.style.width = "100%";
bodyNode.style.height = "100%";
const editorNode = document.createElement("div");
editorNode.classList.add("attachment-container");
editorNode.classList.add("hide");
bodyNode.appendChild(loadingNode);
bodyNode.appendChild(editorNode);
createDialog({
body: bodyNode,
bodyStyle: "width: 80vw; height: 80vh;",
okText: "保存",
...dialogProps,
});
const createEditor = () => {
require.config({
paths: {
vs: "https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.52.2/min/vs",
},
});
require(["vs/editor/editor.main"], () => {
loadingNode.classList.add("hide");
editorNode.classList.remove("hide");
editorNode.classList.add("show");
resolve({
// @ts-ignore
monaco,
editorNode,
});
});
};
await loadScriptByGM(CDNScriptURLEnum.MONACO);
createEditor();
});
};
const showMessage = (type, message, duration = 2e3) => {
const existMessageNode = document.querySelector(".global-message");
if (existMessageNode) {
document.body.removeChild(existMessageNode);
}
const svgSuccess = ``;
const svgError = ``;
const svgMap = /* @__PURE__ */ 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 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 COMMENT_DEFAULT_TEMPLATE_3 = `
📌【复现条件】
┌──────────────────────────────────────────────────────────┐
1.
└──────────────────────────────────────────────────────────┘
🔍【复现步骤】
┌──────────────────────────────────────────────────────────┐
1.
└──────────────────────────────────────────────────────────┘
✅【预期结果】
┌──────────────────────────────────────────────────────────┐
1.
└──────────────────────────────────────────────────────────┘
❌【实际结果】
┌──────────────────────────────────────────────────────────┐
1.
└──────────────────────────────────────────────────────────┘
💡【备注信息】
┌──────────────────────────────────────────────────────────┐
1.
└──────────────────────────────────────────────────────────┘
`;
const BUG_STATUS = {
NEW: "NEW",
ASSIGNED: "ASSIGNED",
REOPENED: "REOPENED",
VERIFIED: "VERIFIED",
RESOLVED: "RESOLVED",
CLOSED: "CLOSED",
};
const RESOLUTION = {
FIXED: "FIXED",
INVALID: "INVALID",
WONTFIX: "WONTFIX",
DUPLICATE: "DUPLICATE",
WORKSFORME: "WORKSFORME",
MOVED: "MOVED",
FIX_NEXT_VER: "FIX_NEXT_VER",
};
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",
AUTO_CLEAR_FIRST_COMMENT_BR: "autoClearFirstCommentBr",
PAGE_DETAIL_CONTROL: "pageDetailControl",
};
const GITLAB_ORIGIN = "http://192.168.1.180:8888";
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) {
showMessage(MessageTypeEnum.ERROR, "此bug已收藏");
return;
}
collectedBugs.push({ id, title, url });
localStorage.setItem(
STORAGE_KEY_MAP.COLLECTED_BUGS,
JSON.stringify({ list: collectedBugs }),
);
showMessage(MessageTypeEnum.SUCCESS, "收藏成功");
};
const setCollectionIcon = (collectionNode, id) => {
if (!collectionNode) {
return;
}
collectionNode.innerHTML = getCollectInfo(id).hasCollected
? `
`
: `
`;
};
const copyText = (text, showDetail = false) => {
if (!text) {
showMessage(MessageTypeEnum.ERROR, "没有可复制的内容");
return;
}
if (typeof GM_setClipboard !== "function") {
showMessage(MessageTypeEnum.ERROR, "当前环境不支持复制功能");
return;
}
if (!showDetail) {
GM_setClipboard(text, "text", () => {
showMessage(MessageTypeEnum.SUCCESS, "复制成功");
});
return;
}
showTextDetail(text, (body) => {
createDialog({
title: "内容详情",
body,
okText: "确定复制",
onOk: (closeDialog) => {
GM_setClipboard(text, "text", () => {
showMessage(MessageTypeEnum.SUCCESS, "复制成功");
closeDialog();
});
},
});
});
};
const showTextDetail = (text, cb) => {
const body = document.createElement("div");
const textareaNode = document.createElement("div");
const texts = text.split("\n");
texts.forEach((item) => {
const span = document.createElement("span");
span.textContent = item;
textareaNode.appendChild(span);
textareaNode.appendChild(document.createElement("br"));
});
textareaNode.style.setProperty("width", "98%");
textareaNode.style.setProperty("height", "96%");
textareaNode.style.setProperty("border", "1px solid #d9d9d9");
textareaNode.style.setProperty("outline", "0px solid transparent");
textareaNode.style.setProperty("padding", "6px");
textareaNode.style.setProperty("border-radius", "4px");
textareaNode.style.setProperty("overflow-y", "scroll");
body.appendChild(textareaNode);
body.style.setProperty("width", "30vw");
body.style.setProperty("height", "30vh");
applyCallBack(cb, body);
};
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: "星期六",
};
const getTodayDate = () => {
const today = /* @__PURE__ */ new Date();
return today.toISOString().split("T")[0];
};
const getSpecialDayBaseToday = (day) => {
const today = /* @__PURE__ */ new Date();
today.setDate(today.getDate() + day);
return today.toISOString().split("T")[0];
};
const getSpecialDayBeforeDate = (target, days) => {
const date = new Date(target);
date.setDate(date.getDate() - days);
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, "0");
const day = String(date.getDate()).padStart(2, "0");
return `${year}-${month}-${day}`;
};
const getDatesInRange = (targetDate, range) => {
const dates = [];
const target = new Date(targetDate);
for (let i = 0; i < range; i++) {
dates.push(getSpecialDayBeforeDate(target, i + 1));
}
return dates;
};
const getDayOfWeek = (textType, dateTime) => {
const days = {
zhou: Object.values(ZHOU_OF_WEEK_MAP),
xingqi: Object.values(XINGQI_OF_WEEK_MAP),
};
const date = new Date(dateTime || getTodayDate());
const dayIndex = date.getDay();
return days[textType][dayIndex];
};
const DEFAULT_PAGE_DETAIL_CONTROL = {
showSaveConfirmDialog: true,
showHintWhenAutoAddReport: true,
showAttechmentDialog: true,
};
const setPageDetailControl = (control) => {
localStorage.setItem(
STORAGE_KEY_MAP.PAGE_DETAIL_CONTROL,
JSON.stringify({ ...DEFAULT_PAGE_DETAIL_CONTROL, ...control }),
);
};
const getPageDetailControl = (key) => {
const controlLocal = JSON.parse(
localStorage.getItem(STORAGE_KEY_MAP.PAGE_DETAIL_CONTROL) || "{}",
);
const control = { ...DEFAULT_PAGE_DETAIL_CONTROL, ...controlLocal };
if (key) {
return control[key];
}
return control;
};
function getReportBugsByDate(date = getTodayDate()) {
const todayReportLocal = JSON.parse(localStorage.getItem(date) ?? "[]");
return todayReportLocal;
}
function isBugInReport(bugId, date = getTodayDate()) {
const todayReportLocal = getReportBugsByDate(date);
return todayReportLocal.some((it) => it.id === bugId);
}
const addBugWithRepeatCheck = (
bug,
date = getTodayDate(),
isSaveForm = false,
) => {
if (isBugInReport(bug.id, date)) {
if (!isSaveForm || getPageDetailControl("showHintWhenAutoAddReport")) {
showMessage(MessageTypeEnum.ERROR, "该BUG已在日报中");
}
return false;
}
const todayReportLocal = getReportBugsByDate(date);
todayReportLocal.push(bug);
localStorage.setItem(date, JSON.stringify(todayReportLocal));
if (!isSaveForm || getPageDetailControl("showHintWhenAutoAddReport")) {
showMessage(MessageTypeEnum.SUCCESS, "添加日报成功");
}
return true;
};
const removeBugFromReport = (bugId, date = getTodayDate()) => {
const todayReportLocal = getReportBugsByDate(date);
const index = todayReportLocal.findIndex((it) => it.id === bugId);
if (index === -1) {
showMessage(MessageTypeEnum.ERROR, "该BUG不存在");
return false;
}
todayReportLocal.splice(index, 1);
localStorage.setItem(date, JSON.stringify(todayReportLocal));
showMessage(MessageTypeEnum.SUCCESS, "移除成功");
return true;
};
const bugHistoryModal = () => {
const div = document.createElement("div");
div.id = "bug_history_vue_app";
document.body.appendChild(div);
const days = getDatesInRange(getSpecialDayBaseToday(1), 14);
const bugHistory = [];
for (let i = 0; i < days.length; i++) {
const date = days[i];
const reportLocal = getReportBugsByDate(date);
if (reportLocal.length > 0) {
const ids = [];
const bugItems = reportLocal;
for (let i2 = 0; i2 < bugItems.length; i2++) {
const bugItem = bugItems[i2];
if (ids.includes(bugItem.id)) {
continue;
}
ids.push(bugItem.id);
bugHistory.push({
date,
bugId: bugItem.id,
bugName: bugItem.name,
bugUrl: bugItem.url,
});
}
}
}
const { createApp, ref, reactive, 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 = Array.from(target.querySelectorAll("pre"));
if (domElements.length === 0) {
domElements = Array.from(target.querySelectorAll("div"));
}
}
domElements.forEach((domElement) => {
const originalHtml = domElement.innerHTML;
const newHtml = replaceHashInPreContent(originalHtml);
domElement.innerHTML = newHtml;
const hashLinks = domElement.querySelectorAll(".commit-hash-link");
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 类型");
};
function clearBrAndBlank(rootNode) {
if (!rootNode || !(rootNode instanceof Node)) {
console.warn("传入的根节点无效,请传入有效的 DOM 节点");
return false;
}
if (rootNode.nodeType !== Node.ELEMENT_NODE) {
return true;
}
const rootElement = rootNode;
const pElements = rootElement.querySelectorAll("p");
if (pElements.length === 0) {
return true;
}
pElements.forEach((pElement) => {
const brElements = Array.from(pElement.querySelectorAll("br"));
brElements.forEach((br) => {
if (br.parentElement === pElement) {
br.remove();
}
});
});
const childNodes = Array.from(rootElement.childNodes);
const pNodeList = Array.from(pElements);
childNodes.forEach((node) => {
var _a;
if (node.nodeType !== Node.TEXT_NODE) return;
const textContent =
((_a = node.textContent) == null ? void 0 : _a.trim()) || "";
if (textContent !== "") return;
const prevSibling = node.previousSibling;
const nextSibling = node.nextSibling;
const prevIsP = prevSibling && pNodeList.includes(prevSibling);
const nextIsP = nextSibling && pNodeList.includes(nextSibling);
if (prevIsP && nextIsP) {
node.remove();
}
});
return true;
}
const renderBugDetail = () => {
var _a, _b, _c, _d;
const persons = getPersonMap();
const table1 = document.querySelector("#bz_show_bug_column_1");
const table2 = document.querySelector("#bz_show_bug_column_2");
const reporterNode = document.querySelector(
"#bz_show_bug_column_2 .vcard .email",
);
const table2AllRows = Array.from(
document.querySelectorAll("#bz_show_bug_column_2 tr"),
);
const reporterEmail = getPersonEmail(
(reporterNode == null ? void 0 : reporterNode.href) ?? "",
);
const reportNodes = Array.from(
document.querySelectorAll(".vcard .email .fn"),
);
const historyBtn = document.querySelector(
"#bz_show_bug_column_2 tr:nth-child(2) a",
);
const editTitleBtn = document.querySelector("#editme_action");
const assigneeEditBtn = document.querySelector("#bz_assignee_edit_action");
const assigneeTakeBtn = document.querySelector("#bz_assignee_take_action");
const markDuplicateBtn = document.querySelector(
"#dup_id_discoverable_action",
);
const markDuplicateBox = document.querySelector("#dup_id_discoverable");
const duplicateSettings = document.querySelector("#duplicate_settings");
const replaceTitleInput = document.querySelector("#summary_alias_input");
const commentTextArea = document.querySelector("#comment");
const commentBox = document.querySelector("#add_comment");
const commentBoxLabel = document.querySelector("#add_comment label");
const attachmentDetails = Array.from(
document.querySelectorAll(
"#attachment_table td[valign='top']:nth-child(2) a",
),
);
const saveFormBtn1 = document.querySelector(
".bz_alias_short_desc_container .knob-buttons input",
);
const saveFormBtn2 = document.querySelector(
"#add_comment .knob-buttons input",
);
const bugStatus = document.querySelector("#bug_status");
const resolution = document.querySelector("#resolution");
const resolutionSettings = document.querySelector("#resolution_settings");
const assigneeInputNode = document.querySelector("#bz_assignee_input");
const assigneeEditNode = document.querySelector(
"#bz_assignee_edit_container",
);
const assignToSelect = document.querySelector("#assigned_to");
const bugTitleBox = document.querySelector("#summary_alias_container");
const bugTitleNode = document.querySelector("#short_desc_nonedit_display");
const bugIDNode = document.querySelector(
".bz_alias_short_desc_container a b",
);
const bugId =
(_a = bugIDNode.innerText.match(/(\d+)$/)) == null ? void 0 : _a[1];
const effectNode = document.querySelector("#cf_effect");
const bzSpacerNodes = Array.from(
document.querySelectorAll(
"#bz_show_bug_column_1 tr:has(td[class='bz_section_spacer'])",
),
);
const navigationNode = document.querySelector(".navigation");
const attachmentNode = document.querySelector(
"#attachment_table .bz_attach_footer a:not(a[id='view_all'])",
);
const attachmentViewAll = document.querySelector(
"#attachment_table .bz_attach_footer a[id='view_all']",
);
const navigationABtns = Array.from(
document.querySelectorAll("#bugzilla-body .navigation a"),
);
const navigationFontBtns = Array.from(
document.querySelectorAll("#bugzilla-body .navigation i font"),
);
const commentNodes = Array.from(
document.querySelectorAll(
"#comments .bz_comment_table .bz_comment:not(.bz_first_comment) .bz_comment_text",
),
);
const firstComment = document.querySelector(
".bz_comment.bz_first_comment .bz_comment_text",
);
const firstCommentHead = document.querySelector(
".bz_comment.bz_first_comment .bz_first_comment_head",
);
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 = contentDocument.querySelector("#header");
const footer = contentDocument.querySelector("#footer");
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) {
createButton(
"配置一键填写",
(button) => {
button.classList.add("plain-button");
bugTitleBox.parentNode.insertBefore(button, bugTitleBox.nextSibling);
},
() => {
gitlabConfigModal();
},
);
createButton(
"自定义快捷分支",
(button) => {
button.classList.add("plain-button");
bugTitleBox.parentNode.insertBefore(button, bugTitleBox.nextSibling);
},
() => newBranchModal(),
);
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 = document.querySelector(
"#bz_assignee_edit_container .email",
);
if (aLink) {
const email = getPersonEmail(aLink.href);
if (email) {
assignToSelect.value = email;
const assignToAppNode = document.querySelector(
"#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 = replaceTitleInput.querySelector("#alias");
const shortDesc = replaceTitleInput.querySelector("#short_desc");
const replaceClone = replaceTitleInput.cloneNode(true);
replaceClone.classList.remove("bz_default_hidden");
const aliasInput = replaceClone.querySelector("#alias");
const shortDescInput = replaceClone.querySelector("#short_desc");
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 = assigneeInputNode.querySelector("br")) == 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", "760px");
commentTextArea.addEventListener("focus", () => {
commentTextArea.rows = 10;
});
}
}
if (attachmentDetails.length) {
const fileNames = Array.from(
document.querySelectorAll(
"#attachment_table td[valign='top']:nth-child(0) b",
),
);
const fileTypeNodes = Array.from(
document.querySelectorAll(
"#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 {
showMessage(
MessageTypeEnum.ERROR,
"文件不存在,或者不支持从此处" + 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 = document.querySelector(
"#assign_to_tester_btn",
);
assignToTesterBtn && assignToTesterBtn.click();
completeBtn && completeBtn.click();
const gitlabConfig = getGitlabConfig();
if (!gitlabConfig) {
showMessage(MessageTypeEnum.ERROR, "请先配置 GitLab 信息");
gitlabConfigModal();
return;
}
const closeMessage = showMessage(
MessageTypeEnum.SUCCESS,
"正在查询相关的 commit 记录...",
1e3 * 60 * 60,
);
const commits = await getBugCommitsFromProjects(bugId);
closeMessage();
if (!commits.length) {
showMessage(
MessageTypeEnum.ERROR,
"没有找到相关的 commit 记录,请检查 Personal Access Token 是否正确,或者修改查询范围",
5e3,
);
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 = {
list: collectedBugs,
};
if (!hasCollected) {
newBugs = {
list: [
...collectedBugs,
{
id: bugIDNode.innerText,
title: bugTitleNode.innerText,
url: window.location.href,
},
],
};
if (collectBugNode.dataset.type !== "no-collected") {
showMessage(
MessageTypeEnum.ERROR,
"数据与页面状态不一致,页面刷新后重试",
);
setTimeout(() => {
window.location.reload();
}, 1e3);
return;
}
showMessage(MessageTypeEnum.SUCCESS, "收藏成功");
} else {
newBugs = {
list:
collectedBugs.length > 0 &&
collectedBugs.filter((bug) => bug.id !== bugIDNode.innerText),
};
if (collectBugNode.dataset.type !== "collected") {
showMessage(
MessageTypeEnum.ERROR,
"数据与页面状态不一致,页面刷新后重试",
);
setTimeout(() => {
window.location.reload();
}, 1e3);
return;
}
showMessage(MessageTypeEnum.SUCCESS, "已取消收藏");
}
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 = contentDocument.querySelector("#header");
const footer = contentDocument.querySelector("#footer");
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) => {
window.open(
`${GITLAB_ORIGIN}/project/${projectName || "bi"}/-/commit/${hash}`,
"_blank",
);
});
});
}
if (
localStorage.getItem(STORAGE_KEY_MAP.AUTO_CLEAR_FIRST_COMMENT_BR) ===
"true" &&
firstComment
) {
clearBrAndBlank(firstComment);
}
if (firstCommentHead) {
const span = document.createElement("span");
span.style.setProperty("display", "inline-flex");
span.style.setProperty("align-items", "center");
span.style.setProperty("transform", "translateY(2px)");
firstCommentHead.appendChild(span);
const checkBox = document.createElement("input");
const checkBoxLabel = document.createElement("label");
checkBoxLabel.classList.add("ml-5");
checkBoxLabel.classList.add("clear-br-label");
checkBoxLabel.innerText = "自动调整本评论文本的上下间距";
checkBoxLabel.title = "仅处理富文本评论。设置后下次自动生效";
checkBox.type = "checkbox";
checkBox.classList.add("ml-5");
span.appendChild(checkBox);
span.appendChild(checkBoxLabel);
checkBox.checked =
localStorage.getItem(STORAGE_KEY_MAP.AUTO_CLEAR_FIRST_COMMENT_BR) ===
"true";
const setCheck = (checked) => {
if (checked) {
clearBrAndBlank(firstComment);
}
checkBox.checked = checked;
localStorage.setItem(
STORAGE_KEY_MAP.AUTO_CLEAR_FIRST_COMMENT_BR,
checked ? "true" : "false",
);
};
checkBoxLabel.addEventListener("click", () => {
setCheck(!checkBox.checked);
});
checkBox.addEventListener("change", (e) => {
setCheck(e.target.checked);
});
firstCommentHead.appendChild(span);
}
};
const showHideFormItemModal = () => {
const div = document.createElement("div");
div.id = "show_hide_formitem_vue_app";
document.body.appendChild(div);
const { createApp, ref, reactive, onUnmounted, watch } = Vue;
const app = createApp({
template: `
控制表单项显示隐藏
mouseenterHandler(item)"
@mouseleave="() => mouseleaveHandler(item)"
@update:checked="updateHandler(item)"
:checked="item.show"
:disabled="item.disabled"
v-if="item.value"
:value="item.value"
:label="item.label"
/>
mouseenterHandler(item)"
@mouseleave="() => mouseleaveHandler(item)"
@update:checked="updateHandler(item)"
:checked="item.show"
:disabled="item.disabled"
:value="item.value"
:label="item.label"
/>
`,
setup() {
const showModal = ref(true);
const modalStyle = ref({
width: "700px",
opacity: "1",
});
const mouseleaveHandler = () => {
modalStyle.value.opacity = "1";
const elem = document.querySelector(
"#show_hide_formitem_vue_app_rect",
);
if (elem) {
elem.remove();
}
};
const { list1, list2 } = getFormItemControls();
const checkboxOptions1 = reactive(list1);
const checkboxOptions2 = reactive(list2);
onUnmounted(() => {
mouseleaveHandler();
});
watch(showModal, (oldValue, newValue) => {
if (newValue !== oldValue) {
mouseleaveHandler();
}
});
return {
showModal,
modalStyle,
checkboxOptions1,
checkboxOptions2,
mouseleaveHandler,
updateHandler: (item) => {
item.show = !item.show;
const elem = document.querySelector(item.value);
if (item.show) {
elem.style.display = "table-row";
} else {
elem.style.display = "none";
}
mouseleaveHandler();
localStorage.setItem(
STORAGE_KEY_MAP.FORM_ITEM_CONTROL,
JSON.stringify({
list1: checkboxOptions1,
list2: checkboxOptions2,
}),
);
modalStyle.value.opacity = "0.5";
},
mouseenterHandler: (item) => {
modalStyle.value.opacity = "0.5";
const elem = document.querySelector(item.value);
const rect = elem.getBoundingClientRect();
const div2 = document.createElement("div");
div2.id = `show_hide_formitem_vue_app_rect`;
div2.style.position = "fixed";
div2.style.top = `${rect.top}px`;
div2.style.left = `${rect.left}px`;
div2.style.width = `${rect.width}px`;
div2.style.height = `${rect.height}px`;
div2.style.backgroundColor = "#9bc0e3";
div2.style.zIndex = "9";
div2.style.opacity = "0.8";
document.body.appendChild(div2);
},
};
},
});
app.use(naive);
return app.mount("#show_hide_formitem_vue_app");
};
const createShowHideBtn = () => {
const bugTitleBox = document.querySelector("#summary_alias_container");
createButton(
"隐藏表单项",
(button) => {
button.classList.add("plain-button");
bugTitleBox.parentNode.appendChild(button);
},
() => {
showHideFormItemModal();
},
);
};
const newCCList = () => {
const persons = getPersonMap();
const ccSelect = document.querySelector("#newcc");
const ccSelectOptions = Array.from(
document.querySelectorAll("#newcc > 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 componentList = () => {
const component = document.querySelector("#component");
if (!component) {
return;
}
const componentOptions = Array.from(
document.querySelectorAll("#component > option"),
);
const div = document.createElement("div");
div.id = "component_list_vue_app";
component.parentNode.insertBefore(div, component);
component.classList.add("bz_default_hidden");
const { createApp, ref, reactive } = Vue;
const app = createApp({
template: `
`,
setup() {
const selectedValue = ref(component.value);
const options = reactive(
componentOptions.map((option) => {
return {
label: option.innerText,
value: option.value,
};
}),
);
return {
selectedValue,
options,
handleUpdateValue(value) {
component.value = value;
const errorComponents = Array.from(
document.querySelectorAll(".validation_error_text"),
);
errorComponents.forEach((error) => {
if (
error.innerText === "You must select a Component for this bug."
) {
error.classList.add("bz_default_hidden");
}
});
},
};
},
});
app.use(naive);
return app.mount("#component_list_vue_app");
};
const featureList = () => {
const feature = document.querySelector("#cf_newfeatureid");
const featureOptions = Array.from(
document.querySelectorAll("#cf_newfeatureid > option"),
);
const div = document.createElement("div");
div.id = "feature_list_vue_app";
feature.parentNode.insertBefore(div, feature);
feature.classList.add("bz_default_hidden");
const { createApp, ref, reactive } = Vue;
const app = createApp({
template: `
`,
setup() {
const selectedValue = ref(feature.value);
const options = reactive(
featureOptions.map((option) => {
return {
label: option.innerText,
value: option.value,
};
}),
);
return {
selectedValue,
options,
handleUpdateValue(value) {
feature.value = value;
},
};
},
});
app.use(naive);
return app.mount("#feature_list_vue_app");
};
const versionList = () => {
const version = document.querySelector("#version");
if (!version) {
return;
}
const versionOptions = Array.from(
document.querySelectorAll("#version > option"),
);
const div = document.createElement("div");
div.id = "version_list_vue_app";
version.parentNode.insertBefore(div, version);
version.classList.add("bz_default_hidden");
const { createApp, ref, reactive } = Vue;
const app = createApp({
template: `
`,
setup() {
const selectedValue = ref(version.value);
const options = reactive(
versionOptions.map((option) => {
return {
label: option.innerText,
value: option.value,
};
}),
);
return {
selectedValue,
options,
handleUpdateValue(value) {
version.value = value;
},
};
},
});
app.use(naive);
return app.mount("#version_list_vue_app");
};
const renderBugDetailPage = () => {
if (PATHNAME === PathNameEnum.BUG_DETAIL) {
renderBugDetail();
assignToList();
createShowHideBtn();
newCCList();
featureList();
componentList();
versionList();
showPageZoomModal();
}
};
const renderBugReportEntry = () => {
const products = Array.from(
document.querySelectorAll("table th[valign='top'] a"),
);
const productDescs = Array.from(
document.querySelectorAll("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 updateQuickSummary = (text, isAdd, isShowMessage = true) => {
let quickSummary = getQuickSummary();
if (isAdd) {
if (quickSummary.some((item) => item.title === text)) {
if (isShowMessage) {
showMessage(MessageTypeEnum.ERROR, "快捷短语已存在");
}
return;
}
quickSummary.push({ title: text });
if (isShowMessage) {
showMessage(MessageTypeEnum.SUCCESS, "添加成功");
}
} else {
quickSummary = quickSummary.filter((item) => item.title !== text);
if (isShowMessage) {
showMessage(MessageTypeEnum.SUCCESS, "删除成功");
}
}
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 quickSummaryModal = () => {
const div = document.createElement("div");
div.id = "quick_summary_vue_app";
document.body.appendChild(div);
const quickSummary = getQuickSummary();
const { createApp, ref, h } = Vue;
const app = createApp({
template: `
自定义快捷短语(更改后刷新页面才生效)
搜索:
新增
`,
setup() {
const showModal = ref(true);
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 {
showModal,
searchValue,
quickSummaryText,
data,
columns,
onSearch,
addQuickSummary,
onPositiveClick: () => {
window.location.reload();
},
};
},
});
app.use(naive);
return app.mount("#quick_summary_vue_app");
};
const countLineBreaks = (str) => {
if (!str) {
return 0;
}
return (str.match(/[\n\r]/g) || []).length;
};
const validateSummary = (value) => {
const errorComponents = Array.from(
document.querySelectorAll(".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 = document.querySelector("#Create");
const allTableCells = newBugForm
? Array.from(newBugForm.querySelectorAll("table tr td"))
: null;
const descriptionTextArea = document.querySelector("#comment");
const versionLabel = document.querySelector("#field_label_version");
const guessNote = document.querySelector("#os_guess_note");
const commit = document.querySelector("#commit");
const shortDesc = document.querySelector("#short_desc");
const attachFalseInput = document.querySelector("#attachment_false input");
const attachTrueInput = document.querySelector("#attachment_true input");
const attatchData = document.querySelector(
"#attachment_true .attachment_entry input",
);
const priority = document.querySelector("#field_label_priority");
const topTip = document.querySelector("form table tr");
const possibleDuplicatesContainer = document.querySelector(
"#possible_duplicates_container",
);
const assignedToHelpLink = document.querySelector(
"#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 = Array.from(
document.querySelectorAll(".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", () => {
quickSummaryModal();
});
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 = document.querySelector("#cke_comment");
if (descriptionCKEEditor) {
descriptionCKEEditor.style.setProperty("display", "none");
}
descriptionTextArea.style.setProperty("display", "block");
descriptionTextArea.style.setProperty("visibility", "visible");
descriptionTextArea.value =
localStorage.getItem(STORAGE_KEY_MAP.NEW_BUG_COMMENT_TEMPLATE) ||
COMMENT_DEFAULT_TEMPLATE_3;
descriptionTextArea.rows =
countLineBreaks(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)
) {
showMessage(MessageTypeEnum.ERROR, "请输入模板内容");
return;
}
localStorage.setItem(
STORAGE_KEY_MAP.NEW_BUG_COMMENT_TEMPLATE,
(descriptionTextArea == null
? void 0
: descriptionTextArea.value) || "",
);
showMessage(MessageTypeEnum.SUCCESS, "模板已更新");
},
);
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);
}
},
() => {
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);
}
},
() => {
descriptionTextArea.rows = 19;
descriptionTextArea.value = COMMENT_DEFAULT_TEMPLATE_2;
},
);
createButton(
"使用模板3",
(btn) => {
btn.classList.add("custom-button");
btn.classList.add("plain-button");
btn.title = COMMENT_DEFAULT_TEMPLATE_3;
if (
descriptionTextArea == null
? void 0
: descriptionTextArea.parentElement
) {
btnGroup.appendChild(btn);
}
},
() => {
descriptionTextArea.rows = 27;
descriptionTextArea.value = COMMENT_DEFAULT_TEMPLATE_3;
},
);
},
);
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 ccList = () => {
const persons = getPersonMap();
const ccSelect = document.querySelector("#cc");
if (!ccSelect) {
return;
}
const ccSelectOptions = Array.from(
document.querySelectorAll("#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 renderBugReportPage = () => {
if (PATHNAME === PathNameEnum.BUG_NEW) {
if (isBugReportPage()) {
renderBugReport();
componentList();
assignToList();
versionList();
featureList();
ccList();
showPageZoomModal();
}
if (isBugReportEntryPage()) {
renderBugReportEntry();
}
}
};
const renderBugReportEntryPage = () => {
if (PATHNAME === PathNameEnum.BUG_NEW_ENTRY) {
renderBugReportEntry();
}
};
const renderBugAttachment = () => {
const attachmentSubmit = document.querySelector(
".attachment_entry input[value='Submit']",
);
if (attachmentSubmit) {
attachmentSubmit.classList.add("custom-button");
}
};
const renderBugAttachmentPage = () => {
if (PATHNAME === PathNameEnum.BUG_ATTACHMENT) {
renderBugAttachment();
}
};
const renderBugHistory = () => {
const table = document.querySelector("#bugzilla-body table");
const tds = Array.from(
document.querySelectorAll("#bugzilla-body table td"),
);
const bugLinks = Array.from(
document.querySelectorAll("#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 addStyle = (css) => {
const style2 = document.createElement("style");
style2.type = "text/css";
style2.innerHTML = css;
document.getElementsByTagName("head")[0].appendChild(style2);
};
const renderBugProcess = () => {
const bugLink = document.querySelector("#bugzilla-body .bz_bug_link");
if (bugLink) {
bugLink.innerText = "返回 " + bugLink.innerText;
bugLink.classList.add("custom-button");
}
};
const renderBugProcessPage = () => {
if (PATHNAME === PathNameEnum.BUG_PROCESS) {
renderBugProcess();
}
};
try {
async function setup() {
addStyle(style);
await loadScriptByGM(CDNScriptURLEnum.VUE);
await loadScriptByGM(CDNScriptURLEnum.NAIVE_UI);
renderBugCommon();
renderBugListPage();
renderBugDetailPage();
renderBugReportPage();
renderBugReportEntryPage();
renderBugAttachmentPage();
renderBugHistoryPage();
renderBugProcessPage();
}
setup();
} catch (error) {
console.error(error);
}
})();