You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无法找到匹配方法:JIRA/Groovy脚本字段计算状态耗时报错

问题分析

你的脚本明显没写完(item.created.getTime...后面的代码缺失),而且逻辑上只考虑了当前时间和变更时间的差,没处理状态变更的完整时间线——要准确计算工单在某状态的停留时长,得跟踪进入状态和离开状态的时间点才行。

先把你提供的不完整代码贴出来:

我尝试计算JIRA工单在某一状态下停留的时长,但遇到了错误。以下是用于脚本字段的Groovy脚本:

import com.atlassian.jira.component.ComponentAccessor
def changeHistoryManager = ComponentAccessor.changeHistoryManager
def currentStatusName = issue?.status?.name
def rt = [0L]
changeHistoryManager.getChangeItemsForField (issue, "status").reverse().each {item -> def timeDiff = System.currentTimeMillis() - item.created.getTime...

解决方案

根据你的需求,分两种场景给你提供完整的可运行脚本:

场景1:计算工单当前状态的停留时长

如果要统计工单从最后一次进入当前状态到现在的时长,用这个脚本:

import com.atlassian.jira.component.ComponentAccessor

def changeHistoryManager = ComponentAccessor.changeHistoryManager
def issueCreatedDate = issue.created.getTime()
def currentTime = System.currentTimeMillis()
def totalDuration = 0L

// 获取所有状态变更记录,按时间正序排列
def statusChanges = changeHistoryManager.getChangeItemsForField(issue, "status")

if (statusChanges.isEmpty()) {
    // 边界情况:工单从未变更过状态,时长从创建到现在
    totalDuration = currentTime - issueCreatedDate
} else {
    def currentStatus = issue.status.name
    def lastEnterTime = issueCreatedDate
    
    // 遍历所有状态变更,找到最后一次进入当前状态的时间
    statusChanges.each { change ->
        def toStatus = change.toString
        def changeTime = change.created.getTime()
        
        if (toStatus == currentStatus) {
            lastEnterTime = changeTime
        }
    }
    
    // 计算从进入当前状态到现在的时长
    totalDuration = currentTime - lastEnterTime
}

// 转换为友好的小时格式(可改成分钟/天,调整除数即可)
def hours = totalDuration / (1000 * 60 * 60)
return String.format("%.2f小时", hours)

场景2:计算工单在指定状态的总停留时长(多次进入累加)

如果要统计工单历史上所有进入目标状态的时长总和(比如多次进入"In Progress"的时间加起来),用这个脚本:

import com.atlassian.jira.component.ComponentAccessor

def changeHistoryManager = ComponentAccessor.changeHistoryManager
def targetStatusName = "In Progress" // 替换成你要统计的状态名称
def issueCreatedDate = issue.created.getTime()
def currentTime = System.currentTimeMillis()
def totalDuration = 0L

def statusChanges = changeHistoryManager.getChangeItemsForField(issue, "status")
def statusTimeline = []

// 把工单创建时间作为初始状态的时间点加入时间线
statusTimeline.add([status: issue.getStatusObject().getOriginalStatus().name, time: issueCreatedDate])

// 把所有状态变更记录加入时间线
statusChanges.each { change ->
    statusTimeline.add([status: change.toString, time: change.created.getTime()])
}

// 加入当前时间,作为时间线的终点
statusTimeline.add([status: issue.status.name, time: currentTime])

// 遍历时间线,累加目标状态的停留时长
for (int i = 0; i < statusTimeline.size() - 1; i++) {
    def currentEntry = statusTimeline[i]
    def nextEntry = statusTimeline[i+1]
    
    if (currentEntry.status == targetStatusName) {
        totalDuration += nextEntry.time - currentEntry.time
    }
}

// 转换为小时格式返回
def hours = totalDuration / (1000 * 60 * 60)
return String.format("%.2f小时", hours)

注意事项

  • 确保脚本字段拥有足够的权限,能调用ComponentAccessor获取changeHistoryManager
  • 状态名称要和JIRA系统里的完全一致(注意大小写、空格,比如不要把"In Progress"写成"InProgress")
  • 如果需要返回纯数字(用于报表或其他计算),可以直接返回hours或者totalDuration,去掉String.format那一行

内容的提问来源于stack exchange,提问作者user1783675

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 08:27:47