# Jira 集成说明
## 概述
为了获取准确的故障次数,系统现在支持从 Jira 直接查询 issue 数量。这样可以避免 Confluence 页面中表格数据为空的问题。
## 问题背景
**463# 信荣海** 的例子:
- Confluence 页面中"故障次数"表格字段是空的(`
| `)
- 但实际在 Jira 中有 2 个故障(FZ-2042、FZ-2043)
- 需要从 Jira 查询获取准确的故障数量
## 新增文件
```
jira_client.py # Jira API 客户端
```
## 环境变量配置
在 `.env` 文件中添加 Jira 配置:
```bash
# Jira 配置
JIRA_URL=https://jira.westwell-lab.com
JIRA_USERNAME=your_username
JIRA_TOKEN=your_api_token
```
## 使用方法
### 1. 修改 shift_report.py 启用 Jira 查询
在 `shift_report.py` 中,找到 `ShiftReportGenerator.__init__` 方法,添加 Jira 客户端:
```python
from jira_client import JiraClient
class ShiftReportGenerator:
def __init__(self):
self.feishu_manager = FeishuScheduleManager()
# Confluence 配置
try:
self.confluence_manager = VesselReportManager()
self.confluence_enabled = True
# 设置 Jira 客户端(用于查询故障数量)
jira_url = os.getenv("JIRA_URL")
jira_username = os.getenv("JIRA_USERNAME")
jira_token = os.getenv("JIRA_TOKEN")
if jira_url and jira_username and jira_token:
jira_client = JiraClient(jira_url, jira_username, jira_token)
self.confluence_manager.set_jira_client(jira_client)
print("Jira 客户端已启用")
except Exception as e:
print(f"Confluence 数据源初始化失败: {e}")
self.confluence_enabled = False
```
### 2. 测试 Jira 查询
创建测试脚本 `test_jira.py`:
```python
import os
import sys
from dotenv import load_dotenv
load_dotenv()
project_root = os.path.dirname(os.path.abspath(__file__))
if project_root not in sys.path:
sys.path.insert(0, project_root)
from jira_client import JiraClient
from confluence import VesselReportManager
# 初始化客户端
jira_client = JiraClient(
os.getenv("JIRA_URL"),
os.getenv("JIRA_USERNAME"),
os.getenv("JIRA_TOKEN")
)
confluence_manager = VesselReportManager()
confluence_manager.set_jira_client(jira_client)
# 获取 463# 的详细数据
print("=== 测试 463# 信荣海的 Jira 查询 ===\n")
# 从 Confluence 获取页面 JQL
import requests
import re
token = os.getenv("CONFLUENCE_TOKEN")
headers = {"Authorization": f"Bearer {token}", "Accept": "application/json"}
url = "https://confluence.westwell-lab.com/rest/api/content/165416156/child/page"
params = {"limit": 100, "expand": "body.storage"}
response = requests.get(url, headers=headers, params=params, timeout=30)
if response.status_code == 200:
data = response.json()
for page in data.get('results', []):
if '463#' in page.get('title', ''):
body = page.get('body', {}).get('storage', {}).get('value', '')
jqls = confluence_manager._extract_jira_jqls(body, "463")
print(f"找到 {len(jqls)} 个 Jira 宏:")
total_issues = 0
for i, jql in enumerate(jqls, 1):
count = jira_client.count_issues(jql)
total_issues += count
print(f"\n宏 {i}:")
print(f" JQL: {jql[:100]}...")
print(f" Issue 数量: {count}")
print(f"\n总计故障数量: {total_issues}")
# 获取具体的 issue keys
all_issues = []
for jql in jqls:
issues = jira_client.get_issue_keys(jql)
all_issues.extend(issues)
print(f"\nIssue Keys: {all_issues}")
break
```
## 工作原理
### 1. 提取 JQL 查询
从 Confluence 页面中提取所有 Jira 宏的 JQL 查询:
```python
def _extract_jira_jqls(self, body: str, vessel_number: str) -> List[str]:
# 查找所有 Jira 宏
jira_macros = re.findall(
r']*ac:name="jira"[^>]*>(.*?)',
body, re.DOTALL
)
for macro in jira_macros:
# 提取 JQL
jql_match = re.search(
r']*name="jqlQuery"[^>]*>(.*?)',
macro, re.DOTALL
)
if jql_match:
jql = jql_match.group(1)
# 检查是否匹配当前船次
if f'实船船次 = "{vessel_number}"' in jql:
jqls.append(jql)
```
### 2. 查询 Jira
对每个 JQL 查询执行 Jira API 调用:
```python
def count_issues(self, jql: str) -> int:
url = f"{self.base_url}/rest/api/2/search"
params = {
"jql": jql,
"maxResults": 0 # 只返回总数
}
response = requests.get(url, auth=self.auth, params=params)
return response.json().get("total", 0)
```
### 3. 故障计数逻辑
1. 首先尝试从 Confluence 表格中提取故障次数
2. 如果表格中没有数据(为 0),则从 Jira 查询
3. 汇总所有匹配的 Jira 宏的 issue 数量
## 注意事项
### 1. Jira API Token
需要在 Jira 中生成 API Token:
1. 登录 Jira
2. 点击头像 -> 账户设置
3. 安全 -> 创建和管理 API 令牌
4. 创建新令牌并保存
### 2. 查询性能
每个船舶报告可能有 3-4 个 Jira 宏,每个宏执行一次 Jira 查询。对于包含多个船舶的报告,可能需要几秒钟完成所有查询。
### 3. 权限要求
Jira 账户需要有权限访问项目 FZ 的 issues。
## 故障排查
### Jira 查询返回 0
检查:
1. Jira 认证信息是否正确
2. 账户是否有权限访问 FZ 项目
3. JQL 查询是否正确(可以在 Jira 中手动测试)
### Confluence 页面没有 Jira 宏
有些船舶页面可能没有创建 Jira 宏,这时会显示表格中的数据(可能为 0 或空)。
## 示例输出
启用 Jira 查询后的输出示例:
```
实船作业:463# 信荣海
上场车辆数:6
作业量/效率:28TEU(20尺*20 40尺*4),0.00循环/车/小时
故障次数/故障率:2次,14.29% <-- 从 Jira 查询获得
人工介入次数/介入率:0次,0.00%
```
如果没有启用 Jira:
```
实船作业:463# 信荣海
上场车辆数:6
作业量/效率:28TEU(20尺*20 40尺*4),0.00循环/车/小时
故障次数/故障率:0次,0.00% <-- 从 Confluence 表格获得(为空)
人工介入次数/介入率:0次,0.00%
```