feat: 交接班报告支持 Confluence/Jira 集成,添加 N/A 记录时间归属功能
- 集成 Confluence API 获取船舶报告数据 - 集成 Jira API 查询故障数量 - 支持船号显示 (462#、463# 等) - 支持故障次数/故障率、人工介入次数/介入率显示 - 跨班作业使用 Card 69 按时间查询效率 - 不跨班作业使用整船效率(剔除异常) - N/A 记录根据作业时间归属到对应船舶 - 更新 AGENTS.md 和 README.md 文档 - 删除 daily_report_gui.py
This commit is contained in:
230
JIRA_INTEGRATION.md
Normal file
230
JIRA_INTEGRATION.md
Normal file
@@ -0,0 +1,230 @@
|
||||
# Jira 集成说明
|
||||
|
||||
## 概述
|
||||
|
||||
为了获取准确的故障次数,系统现在支持从 Jira 直接查询 issue 数量。这样可以避免 Confluence 页面中表格数据为空的问题。
|
||||
|
||||
## 问题背景
|
||||
|
||||
**463# 信荣海** 的例子:
|
||||
- Confluence 页面中"故障次数"表格字段是空的(`<td><br /></td>`)
|
||||
- 但实际在 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:structured-macro[^>]*ac:name="jira"[^>]*>(.*?)</ac:structured-macro>',
|
||||
body, re.DOTALL
|
||||
)
|
||||
|
||||
for macro in jira_macros:
|
||||
# 提取 JQL
|
||||
jql_match = re.search(
|
||||
r'<ac:parameter[^>]*name="jqlQuery"[^>]*>(.*?)</ac:parameter>',
|
||||
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%
|
||||
```
|
||||
Reference in New Issue
Block a user