jira工具箱

jiar工具箱

// ==UserScript==
// @name         jira工具箱
// @namespace    qigege
// @version      1.1.0
// @description  jiar工具箱
// @author       qgg
// @match        http://172.19.5.17:8888/browse/*
// @match        http://jira.xquant.com:8888/browse/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=5.17
// @grant        none
// @license      MIT
// ==/UserScript==

(function () {
    'use strict';

    function copyLog() {
        const version = document.querySelector("#fixVersions-field")?.innerText || "";
        const lis = document.querySelector(".aui-nav-breadcrumbs").children;
        const isBug = document.querySelector("#type-val").innerText.includes("缺陷");

        let jiraId = "", summary = "", bugId = "", problem = "";

        if (isBug) {
            if (lis.length === 2) {
                bugId = lis[1].innerText;
                problem = document.querySelector("#summary-val").innerText;
            } else {
                const [id, ...rest] = lis[1].innerText.split(' ');
                jiraId = id;
                summary = rest.join(' ');
                bugId = lis[2].innerText;
                problem = document.querySelector("#summary-val").innerText;
            }
        } else {
            jiraId = lis[1].innerText;
            summary = document.querySelector("#summary-val").innerText;
        }

        const content = `版本:${version} \n需求编号:${jiraId} \n内容概要:${summary} \n缺陷编号:${bugId} \n问题描述:${problem} `;
        addClipboard(content);
    }

    function copyFileName() {
        const user = document.querySelector("#header-details-user-fullname").getAttribute("data-displayname");
        const jiraId = document.querySelector(".aui-nav-breadcrumbs").children[1].innerText;
        const summary = document.querySelector("#summary-val").innerText;
        const client = document.querySelector("#customfield_10503-val").innerText;

        const content = client.includes("中信") ? `【${jiraId}】需求:${summary} ` : `${jiraId}_${user}_${summary} `;
        addClipboard(content);
    }

    function calculateRows(content) {
        const lines = content.split('\n');
        return lines.length + 1;
    }

    function createDoc() {
        backboard.hidden = false;

        const user = document.querySelector("#header-details-user-fullname").getAttribute("data-displayname");
        const jiraId = document.querySelector(".aui-nav-breadcrumbs").children[1].innerText;
        const summary = document.querySelector("#summary-val").innerText;
        const client = document.querySelector("#customfield_10503-val").innerText;

        if (client.includes("中信")) {
            showFloatingMessage("抱歉,暂不支持中信!");
            backboard.hidden = true;
            return;
        }

        const fileName = `${jiraId}_${user}_${summary} `

        const analysis = document.querySelector(".user-content-block")
            ? document.querySelector(".user-content-block").innerText.trimStart() : "无";
        const sln = document.querySelector("#customfield_10910-val")
            ? document.querySelector("#customfield_10910-val").innerText.trimStart() : "无";
        const sugg = document.querySelector("#customfield_11700-val")
            ? document.querySelector("#customfield_11700-val").innerText.trimStart() : "无";

        const dialog = createDialog("Auto Create Doc", [
            createNewDocField('文件名称', "x-file-name", fileName, 1),
            createNewDocField('需求描述', "x-desc", "无", 1),
            createNewDocField('需求分析', "x-analyes", analysis, calculateRows(analysis)),
            createNewDocField('解决方案', "x-sln", sln, calculateRows(sln)),
            createNewDocField('测试建议', "x-sugg", sugg, calculateRows(sugg)),
            createNewDocField('自测场景', "x-self-text", "无", 1),
            createNewDocField('相关脚本', "x-script", "无", 1)
        ], () => {
            const content =
                `【需求描述】\n${document.querySelector("#x-desc").value} \n
【需求分析】\n${document.querySelector("#x-analyes").value} \n
【解决方案】\n${document.querySelector("#x-sln").value} \n
【测试建议】\n${document.querySelector("#x-sugg").value} \n
【自测场景】\n${document.querySelector("#x-self-text").value} \n
【相关脚本】\n${document.querySelector("#x-script").value}
`;
            downloadFile(`${fileName}.txt`, content);
            backboard.hidden = true;
            document.body.removeChild(dialog);
        });

        document.body.appendChild(dialog);
    }

    function createNewDocField(label, id, content, rows = 3) {
        const field = document.createElement('div');
        field.className = "field-group";
        field.style.marginBottom = "20px";

        const labelElement = document.createElement('label');
        labelElement.innerHTML = label;
        labelElement.style.display = "inline-block";
        labelElement.style.width = "100px";
        labelElement.style.verticalAlign = "top"; // 修改为top,使label和输入框平齐
        field.appendChild(labelElement);

        const textBox = document.createElement('textarea');
        textBox.id = id;
        textBox.className = "textarea long-field";
        textBox.rows = rows;
        textBox.cols = 95;
        textBox.style.border = "2px solid var(--aui-form-field-border-color)";
        textBox.style.transition = "background-color 0.2s ease-in-out, border-color 0.2s ease-in-out";
        textBox.style.resize = "vertical";
        textBox.style.verticalAlign = "top"; // 修改为top,使label和输入框平齐
        textBox.style.fontFamily = "inherit";
        textBox.style.boxSizing = "border-box";
        textBox.style.borderRadius = "3.01px";

        textBox.textContent = content;

        textBox.addEventListener('mouseover', () => textBox.style.backgroundColor = "var(--aui-form-field-hover-bg-color)");
        textBox.addEventListener('mouseout', () => textBox.style.backgroundColor = "");
        textBox.addEventListener('mousedown', () => textBox.style.backgroundColor = "");

        field.appendChild(textBox);
        return field;
    }

    function closeRightPanel() {
        const sidebar = document.querySelector("#viewissuesidebar");
        sidebar.style.display = sidebar.style.display === 'none' ? "" : 'none';
    }

    function setting() {
        backboard.hidden = false;

        const dialog = createDialog("Jira Tool Box Settings", [
            createSettingField('Copy Log', 'addCopyLog', true),
            createSettingField('Copy FileName', 'addCopyFileName'),
            createSettingField('Create Doc', 'addCreateDoc', true),
            createSettingField('Close Right Panel', 'addCloseRightPanel'),
            createSettingField('Setting(reset need clear cache)', 'addSetting', true)
        ], () => {
            localStorage.setItem('addCopyLog', document.querySelector('#addCopyLog').checked);
            localStorage.setItem('addCopyFileName', document.querySelector('#addCopyFileName').checked);
            localStorage.setItem('addCreateDoc', document.querySelector('#addCreateDoc').checked);
            localStorage.setItem('addCloseRightPanel', document.querySelector('#addCloseRightPanel').checked);
            localStorage.setItem('addSetting', document.querySelector('#addSetting').checked);

            addCopyLog = localStorage.getItem('addCopyLog') === "true";
            addCopyFileName = localStorage.getItem('addCopyFileName') === "true";
            addCreateDoc = localStorage.getItem('addCreateDoc') === "true";
            addCloseRightPanel = localStorage.getItem('addCloseRightPanel') === "true";
            addSetting = localStorage.getItem('addSetting') === "true";

            backboard.hidden = true;
            document.body.removeChild(dialog);
            init();
        });

        document.body.appendChild(dialog);
    }

    function createSettingField(label, id, defaultCheck = false) {
        const field = document.createElement('div');
        field.className = "field-group";
        field.style.marginBottom = "20px";

        const labelElement = document.createElement('label');
        labelElement.innerHTML = label;
        labelElement.style.display = "inline-block";
        labelElement.style.width = "220px";
        labelElement.style.verticalAlign = "middle";
        field.appendChild(labelElement);

        const checkbox = document.createElement('input');
        checkbox.type = "checkbox";
        checkbox.id = id;
        if (localStorage.getItem(id) === 'true') {
            checkbox.checked = true;
        }
        else {
            checkbox.checked = defaultCheck;
        }
        checkbox.style.verticalAlign = "middle";
        field.appendChild(checkbox);

        return field;
    }

    function createDialog(title, fields, onSave) {
        const dialog = document.createElement('div');
        dialog.className = "jira-dialog jira-dialog-core box-shadow jira-dialog-open popup-width-large jira-dialog-content-ready";
        dialog.style = `
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
max-height: 80%;
overflow: hidden;
display: flex;
flex-direction: column;
`;

        const header = document.createElement('div');
        header.className = "jira-dialog-heading jira-dialog-core-heading";
        header.innerHTML = `<h2> ${title}</h2> `;
        header.style.flexShrink = '0';
        dialog.appendChild(header);

        const content = document.createElement('div');
        content.className = "jira-dialog-content jira-dialog-core-content";
        content.style.flexGrow = '1';
        content.style.overflowY = 'auto';
        dialog.appendChild(content);

        const form = document.createElement('div');
        form.className = "form-body";
        fields.forEach(field => form.appendChild(field));
        content.appendChild(form);

        const btnContainer = document.createElement('div');
        btnContainer.className = "buttons-container form-footer";
        btnContainer.style.flexShrink = '0';

        const btns = document.createElement('div');
        btns.className = "buttons";
        btnContainer.appendChild(btns);

        const okBtn = document.createElement('a');
        okBtn.className = "aui-button toolbar-trigger issueaction-workflow-transition";
        okBtn.innerHTML = "保存";
        okBtn.addEventListener('click', onSave);
        btns.appendChild(okBtn);

        const cancelBtn = document.createElement('a');
        cancelBtn.innerHTML = "取消";
        cancelBtn.className = "aui-button aui-button-link cancel";
        cancelBtn.addEventListener('click', () => {
            backboard.hidden = true;
            document.body.removeChild(dialog);
        });
        btns.appendChild(cancelBtn);
        dialog.appendChild(btnContainer);

        // 添加Esc键关闭功能
        document.addEventListener('keydown', function (event) {
            if (event.key === 'Escape') {
                backboard.hidden = true;
                document.body.removeChild(dialog);
            }
        });

        return dialog;
    }

    function downloadFile(filename, content) {
        const element = document.createElement('a');
        element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(content));
        element.setAttribute('download', filename);
        element.style.display = 'none';
        document.body.appendChild(element);
        element.click();
        document.body.removeChild(element);
    }

    function addClipboard(content) {
        const textarea = document.createElement('textarea');
        textarea.value = content;
        document.body.appendChild(textarea);
        textarea.select();
        document.execCommand('copy');
        document.body.removeChild(textarea);

        showFloatingMessage("已将以下内容增加到剪切板\n\n" + content);
    }

    function addOpsbarButton(needAdd, label, action, tooltip) {
        const id = label.replaceAll(' ', '');
        const existingButton = document.querySelector('#' + id);
        if (needAdd && !existingButton) {
            document.querySelector("#opsbar-opsbar-transitions").appendChild(createButton(label, action, tooltip));
        } else if (!needAdd && existingButton) {
            existingButton.remove();
        }
    }

    function createButton(label, clickHandler, tooltip) {
        const btn = document.createElement('a');
        btn.className = "aui-button toolbar-trigger issueaction-workflow-transition";
        btn.href = "#";
        btn.id = label.replaceAll(' ', '');
        btn.title = tooltip;
        const span = document.createElement('span');
        span.className = "trigger-label";
        span.innerHTML = label;
        btn.appendChild(span);
        btn.addEventListener('click', clickHandler);
        return btn;
    }

    function showFloatingMessage(message) {
        const floatingDiv = document.createElement('div');
        floatingDiv.style.position = 'fixed';
        floatingDiv.style.top = '20px';
        floatingDiv.style.left = '50%';
        floatingDiv.style.transform = 'translateX(-50%)';
        floatingDiv.style.padding = '10px 20px';
        floatingDiv.style.backgroundColor = 'rgba(0, 0, 0, 0.7)';
        floatingDiv.style.color = 'white';
        floatingDiv.style.borderRadius = '5px';
        floatingDiv.style.zIndex = '9999';
        floatingDiv.style.opacity = '0';
        floatingDiv.style.transition = 'opacity 0.5s ease-in-out';
        floatingDiv.innerHTML = message.replace(/\n/g, '<br>');

        document.body.appendChild(floatingDiv);

        // 渐入动画
        setTimeout(() => {
            floatingDiv.style.opacity = '1';
        }, 10);

        // 渐出动画
        setTimeout(() => {
            floatingDiv.style.opacity = '0';
            floatingDiv.addEventListener('transitionend', () => {
                document.body.removeChild(floatingDiv);
            });
        }, 4500);
    }

    function init() {
        addOpsbarButton(addCopyLog, 'Copy Log', copyLog, "快捷复制svn提交log");

        if (document.querySelector("#type-val").innerText.includes("需求")) {
            addOpsbarButton(addCopyFileName, 'Copy FileName', copyFileName, "快捷复制文档名称");
            addOpsbarButton(addCreateDoc, 'Create Doc', createDoc, "快捷创建文档,支持jira维护后一键生成文档");
        }

        addOpsbarButton(addCloseRightPanel, 'Close Right Panel', closeRightPanel, "关闭右侧栏");
        addOpsbarButton(addSetting, 'Setting', setting, "设置");
    }

    let addCopyLog = false;
    let addCopyFileName = false;
    let addCreateDoc = false;
    let addCloseRightPanel = false;
    let addSetting = false;

    const backboard = document.createElement('div');
    backboard.className = "aui-blanket";
    backboard.hidden = true;
    document.body.appendChild(backboard);

    if (localStorage.getItem('addCopyLog') === null) {
        setting();
    } else {
        addCopyLog = localStorage.getItem('addCopyLog') === "true";
        addCopyFileName = localStorage.getItem('addCopyFileName') === "true";
        addCreateDoc = localStorage.getItem('addCreateDoc') === "true";
        addCloseRightPanel = localStorage.getItem('addCloseRightPanel') === "true";
        addSetting = localStorage.getItem('addSetting') === "true";
    }

    init();
    setInterval(init, 2000);
})();