Page tree
Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

Version 1 Next »

1、必填:工作流的必填会受到插件的影响,这里只是取了字段方案里的必填信息。

2、权限:Condition这里没有提取,因为也是存在插件原因范围比较难确定。

import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.workflow.JiraWorkflow
import com.atlassian.jira.issue.fields.screen.FieldScreen
import com.atlassian.jira.issue.fields.screen.FieldScreenTab
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.fields.CustomField;

def fieldLayoutManager = ComponentAccessor.getFieldLayoutManager()
def workflowManager = ComponentAccessor.getWorkflowManager()
def fieldScreenManager = ComponentAccessor.getFieldScreenManager()
def fieldManager = ComponentAccessor.getFieldManager()

//指定一下Issue获取工作流
MutableIssue issue = Issues.getByKey('DEMO-32') as MutableIssue
JiraWorkflow workflow = workflowManager.getWorkflow(issue)

def out = new StringBuilder()
out << "<h2>${workflow.name}</h2>"
out << "<table class='aui' id='myTable'>"
out << "<tr><th>状态(From -> To)</th><th>动作/转换</th><th>填写字段</th><th>是否必填</th><th>字段选项</th></tr>"

workflow.getAllActions().each { action ->
    def transitionName = action.getName()
    def screenId = action.getMetaAttributes()?.get("jira.fieldscreen.id")
    //排除掉创建页面
    if("Create".equals(transitionName)) {
        return
    }

    // 拼 from → to 状态
    def statusDesc = workflow.getStepsForTransition(action).collect { step ->
        def fromStatus = step.getName()
        def toStatus = workflow.getDescriptor().getStep(action.getUnconditionalResult().getStep()).getName()
        "${fromStatus} -> ${toStatus}"
    }.join("<br>")

    action.getConditionalResults()

    if (screenId) {
        FieldScreen screen = fieldScreenManager.getFieldScreen(screenId as Long)


        // 收集字段
        def fieldRows = []
        screen?.getTabs()?.each { FieldScreenTab tab ->
            tab.getFieldScreenLayoutItems().each { item ->
                def fieldId = item.getFieldId()
                def field = fieldManager.getField(fieldId)
                def layout = fieldLayoutManager.getFieldLayout(issue)
                def required = layout?.getFieldLayoutItem(fieldId)?.isRequired() ? '必填' : ''
                def optionsText = ""
                if (field instanceof CustomField) {
                    optionsText = getOptions(field as CustomField, issue)
                }
                fieldRows << [name: field?.name, id: fieldId, required: required,
                    options: optionsText]
            }
            
        }
        // 🔽 排序:先按字段名,再按 ID
        fieldRows.sort { a, b -> 
            b.required <=> a.required
        }

        if (fieldRows) {
            def rowspan = fieldRows.size()
            // 第一行带 rowspan
            def first = fieldRows[0]
            out << "<tr><td rowspan='${rowspan}'>${statusDesc}</td>"
            out << "<td rowspan='${rowspan}'>${transitionName} (${screen?.name})</td>"
            out << "<td>${first.name} (${first.id})</td><td>${first.required}</td><td>${first.options}</td></tr>"

            // 剩余行
            fieldRows.drop(1).each { f ->
                out << "<tr><td>${f.name} (${f.id})</td><td>${f.required}</td><td>${f.options}</td></tr>"
            }
        } else {
            //界面没有字段,默认输入备注
            log.warn("============================${screen.name}")
            out << "<tr><td>${statusDesc}</td>"
            out << "<td>${transitionName} (${screen?.name})</td>"
            out << "<td>备注</td><td></td><td></td></tr>"
        }
    } else {
        out << "<tr><td>${statusDesc}</td><td>${transitionName}(无输入项)</td><td colspan='3'> </td></tr>"
    }
}

out << "</table>"

// 在表格前加按钮
out.insert(out.indexOf("<h2>"),
    """
    <button class='aui-button'
        onclick="
            var table=document.getElementById('myTable')||document.querySelector('table');
            if(!table)return;
            var html=table.outerHTML;
            var text=table.innerText;
            navigator.clipboard.write([
                new ClipboardItem({
                    'text/html': new Blob([html], {type: 'text/html'}),
                    'text/plain': new Blob([text], {type: 'text/plain'})
                })
            ]).then(function(){
                var myFlag = AJS.flag({
                    type: 'success',
                    body: '复制成功',
                    duration: 1000,
                    close: 'auto'
                });
            }).catch(function(err){
                console.error(err);
                alert('复制失败,浏览器可能不支持 ClipboardItem API');
            });
        ">
        复制表格
    </button>
    """
)

return out.toString()

// 获取某个字段的全部选项(仅限选择类字段)
def getOptions(CustomField cf, MutableIssue issue) {
def optionsManager = ComponentAccessor.getOptionsManager()
    def config = cf.getRelevantConfig(issue)
    if (!config) {
        return ""
    }
    def options = optionsManager.getOptions(config)
    if (!options) {
        return ""
    }
    return options.collect { opt ->
        (opt.disabled ? "[禁用] " : "") + opt.value
    }.join(" / ")
}



  • No labels