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

JIRA Forge开发:如何在问题状态改为Done时打开ModalDialog

实现方案说明

你当前编写的是Jira Forge的产品事件处理函数,这类函数运行在Atlassian的服务端,无法直接操作前端页面的DOM或唤起UI组件,所以不能在这个函数里直接调用ModalDialog。

可行实现思路

我们采用「前端页面埋点监听状态变更 + 前端唤起模态框」的方案,同时可以保留你的后端逻辑做数据校验或业务处理,具体步骤如下:

第一步:调整应用清单(manifest.yml)配置

你需要注册两个前端模块,分别覆盖问题详情页和看板页的场景,同时声明必要的权限:

modules:
  jira:issueView:
    - key: done-status-modal-issue-view
      resource: main
      title: 完成状态模态框
  jira:boardView:
    - key: done-status-modal-board-view
      resource: main
      title: 看板完成状态模态框
resources:
  - key: main
    path: src/frontend/index.jsx
permissions:
  scopes:
    - read:jira-work
    - write:jira-work
app:
  id: 你的应用ID

第二步:前端实现状态监听与模态框唤起

以UI Kit 2 + React为例,前端代码逻辑如下:

import React, { useState, useEffect } from 'react';
import { ModalDialog, Button } from '@forge/react';
import { view } from '@forge/jira-bridge';

const DONE = 'Done';

const App = () => {
  const [isModalOpen, setIsModalOpen] = useState(false);
  const [issueSummary, setIssueSummary] = useState('');

  useEffect(() => {
    // 监听问题详情页的状态变更事件
    const unsubscribe = view.addEventListener('jira:issue:updated', async (event) => {
      const { issue } = event.data;
      const newStatus = issue.fields.status.name;
      
      // 匹配你原来的状态判断逻辑
      if (newStatus === DONE) {
        setIssueSummary(issue.fields.summary);
        setIsModalOpen(true);
      }
    });

    // 监听看板页拖拽变更问题状态的事件
    const boardUnsubscribe = view.addEventListener('jira:board:issue:updated', async (event) => {
      const { issue, newStatus } = event.data;
      if (newStatus.name === DONE) {
        setIssueSummary(issue.fields.summary);
        setIsModalOpen(true);
      }
    });

    return () => {
      unsubscribe();
      boardUnsubscribe();
    };
  }, []);

  return (
    <>
      {isModalOpen && (
        <ModalDialog header="问题已完成" onClose={() => setIsModalOpen(false)}>
          <p>问题 {issueSummary} 已被标记为完成</p>
          <Button onClick={() => setIsModalOpen(false)}>确认</Button>
        </ModalDialog>
      )}
    </>
  );
};

export default App;

第三步:原有后端逻辑的复用

如果你原来的run函数中还有其他业务逻辑(比如数据统计、关联其他系统操作),可以将其改造为Forge Resolver,前端在唤起模态框前调用Resolver执行逻辑即可:

// 后端resolver代码
import Resolver from '@forge/resolver';
const resolver = new Resolver();

const DONE = 'Done';

resolver.define('checkIssueStatus', async ({ payload }) => {
  const { issue } = payload;
  // 此处可复用你原来的业务逻辑
  return {
    shouldOpenModal: issue.fields.status.name === DONE,
    description: issue.fields.summary
  };
});

export const run = resolver.getDefinitions();

前端调用Resolver的逻辑:

import { invoke } from '@forge/bridge';

// 在状态变更的监听回调里调用
const result = await invoke('checkIssueStatus', { issue: event.data.issue });
if (result.shouldOpenModal) {
  setIssueSummary(result.description);
  setIsModalOpen(true);
}

注意事项

  • 该方案可以同时覆盖「问题详情页修改状态」和「看板页拖拽修改状态」两种场景
  • 如果你的模态框需要展示更复杂的内容,可以直接在ModalDialog组件内扩展即可
  • 如果需要限制仅特定角色/项目触发弹窗,可以在状态判断逻辑里加对应的权限校验

内容的提问来源于stack exchange,提问作者Joaquín L. Robles

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 10:12:01