Jira Bug Copier

在Jira Bug清单页面一键复制Jira Bug信息

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

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

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

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

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

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name         Jira Bug Copier
// @namespace    http://tampermonkey.net/
// @version      1.0.2
// @description  在Jira Bug清单页面一键复制Jira Bug信息
// @author       ChangXiaoqiang
// @match        *://*.com/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    // 添加样式
    const style = document.createElement('style');
    style.textContent = `
        .copy-button {
            background: #0052CC;
            color: white;
            border: none;
            border-radius: 2px;
            padding: 0px 4px;
            font-size: 9px;
            cursor: pointer;
            margin-left: 4px;
            height: 16px;
            line-height: 16px;
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
        }

        .copy-button:active {
            background: #0747A6;
        }
    `;
    document.head.appendChild(style);

    // 添加辅助函数:从指定行中获取 Bug Link
    function getBugLink(row) {
        // 尝试直接从第一列获取第二个链接(绝大多数情况下 Bug ID 就在这里)
        let link = row.querySelector('td:first-child a:nth-of-type(2)');
        if (link) {
            console.log("【辅助函数】通过 td:first-child a:nth-of-type(2) 找到 Bug Link:", link);
            return link;
        }
        // 如果上面方式未命中,则尝试获取所有 a.issue-link 的第一个(可能是备用方案)
        link = row.querySelector('a.issue-link');
        if (link) {
            console.log("【辅助函数】通过 a.issue-link 找到 Bug Link:", link);
            return link;
        }
        return null;
    }

    // 添加按钮的主函数
    function addCopyButtons() {
        // 获取 bug 列表的所有行(同时考虑页面 DOM 和 issuetable-web-component 内的 Shadow DOM)
        let bugRows = Array.from(document.querySelectorAll('tr[class*="issuerow"]'));
        const issuetable = document.querySelector('issuetable-web-component');
        if (issuetable && issuetable.shadowRoot) {
            bugRows = bugRows.concat(Array.from(issuetable.shadowRoot.querySelectorAll('tr[class*="issuerow"]')));
        }

        if (bugRows.length === 0) {
            // 如果没有找到行,等待100ms后重试
            setTimeout(addCopyButtons, 100);
            return;
        }

        bugRows.forEach(row => {
            // 检查是否已经添加过按钮
            if (row.querySelector('.copy-button')) {
                return;
            }

            // 创建拷贝按钮
            const copyButton = document.createElement('button');
            copyButton.className = 'copy-button';
            copyButton.textContent = '拷贝';

            copyButton.addEventListener('click', () => {
                // 直接调用辅助函数从当前行提取 Bug Link
                const bugLink = getBugLink(row);
                if (!bugLink) {
                    console.error("无法找到 Bug Link,请检查 DOM 结构:", row.innerHTML);
                    return;
                }
                // 尝试从元素中获取 Bug ID
                let bugId = bugLink.textContent.trim();
                if (!bugId) {
                    // 如果 textContent 为空,则使用 data-issue-key 或 title 属性作为备用
                    bugId = bugLink.getAttribute("data-issue-key") || bugLink.getAttribute("title") || "";
                    console.log("【辅助函数】使用属性获取 Bug ID:", bugId);
                }
                if (!bugId) {
                    console.error("无法获取到 Bug ID,请检查 Bug Link 元素:", bugLink);
                    return;
                }

                // 获取标题
                const title = row.querySelector('td[class*="summary"] a.issue-link').textContent.trim();

                // 获取严重度
                const severity = row.querySelector('td[class*="customfield_11982"]').textContent.trim();

                // 组合文本 - 严重度用[]标记
                const textToCopy = `[${severity}] ${bugId} ${title}`;

                // 拷贝到剪贴板
                navigator.clipboard.writeText(textToCopy).then(() => {
                    copyButton.textContent = '已拷贝!';
                    setTimeout(() => {
                        copyButton.textContent = '拷贝';
                    }, 1000);
                });
            });

            // 将按钮添加到行中
            const firstCell = row.querySelector('td');
            if (firstCell) {
                firstCell.appendChild(copyButton);
            }
        });
    }

    // 监听页面变化
    const observer = new MutationObserver((mutations) => {
        addCopyButtons();
    });

    // 开始观察
    observer.observe(document.body, {
        childList: true,
        subtree: true
    });

    // 初始调用
    addCopyButtons();
})();