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:
Developer
2026-03-14 02:52:23 +08:00
parent cc989a8ddb
commit 5d0cafac32
13 changed files with 1746 additions and 394 deletions

155
confluence/client.py Normal file
View File

@@ -0,0 +1,155 @@
"""
Confluence API 客户端
提供与 Confluence REST API 交互的基础功能。
"""
import requests
import json
from typing import Optional, Dict, List, Any
from datetime import datetime
class ConfluenceClient:
"""Confluence API 客户端"""
def __init__(self, base_url: str, token: str):
"""
初始化 Confluence 客户端
Args:
base_url: Confluence 基础 URL (如 https://confluence.example.com)
token: API 访问令牌 (Personal Access Token)
"""
self.base_url = base_url.rstrip("/")
self.token = token
self.headers = {
"Authorization": f"Bearer {token}",
"Accept": "application/json",
"Content-Type": "application/json",
}
def _make_request(
self,
method: str,
endpoint: str,
params: Optional[Dict] = None,
json_data: Optional[Dict] = None,
) -> Optional[Dict]:
"""
发送 HTTP 请求
Args:
method: HTTP 方法 (GET, POST, etc.)
endpoint: API 端点路径
params: 查询参数
json_data: JSON 请求体
Returns:
响应数据字典,失败返回 None
"""
url = f"{self.base_url}{endpoint}"
try:
response = requests.request(
method=method,
url=url,
headers=self.headers,
params=params,
json=json_data,
timeout=30,
)
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
print(f"请求失败: {url}, 错误: {e}")
return None
def get_page(self, page_id: str, expand: Optional[str] = None) -> Optional[Dict]:
"""
获取页面信息
Args:
page_id: 页面 ID
expand: 需要展开的内容 (如 "body.view,body.storage")
Returns:
页面数据字典
"""
endpoint = f"/rest/api/content/{page_id}"
params = {}
if expand:
params["expand"] = expand
return self._make_request("GET", endpoint, params=params)
def get_child_pages(
self, parent_id: str, limit: int = 100, expand: Optional[str] = None
) -> List[Dict]:
"""
获取子页面列表
Args:
parent_id: 父页面 ID
limit: 返回结果数量限制
expand: 需要展开的内容
Returns:
子页面列表
"""
endpoint = f"/rest/api/content/{parent_id}/child/page"
params = {"limit": limit}
if expand:
params["expand"] = expand
result = self._make_request("GET", endpoint, params=params)
if result and "results" in result:
return result["results"]
return []
def search_content(
self, query: str, space_key: Optional[str] = None, limit: int = 50
) -> List[Dict]:
"""
搜索内容
Args:
query: 搜索关键词 (CQL)
space_key: 空间 Key (可选)
limit: 返回结果数量限制
Returns:
搜索结果列表
"""
endpoint = "/rest/api/content/search"
cql = query
if space_key:
cql = f"{query} AND space = {space_key}"
params = {"cql": cql, "limit": limit}
result = self._make_request("GET", endpoint, params=params)
if result and "results" in result:
return result["results"]
return []
def get_page_by_title(
self, space_key: str, title: str, expand: Optional[str] = None
) -> Optional[Dict]:
"""
根据标题获取页面
Args:
space_key: 空间 Key
title: 页面标题
expand: 需要展开的内容
Returns:
页面数据字典
"""
endpoint = "/rest/api/content"
params = {"spaceKey": space_key, "title": title, "limit": 1}
if expand:
params["expand"] = expand
result = self._make_request("GET", endpoint, params=params)
if result and "results" in result and len(result["results"]) > 0:
return result["results"][0]
return None