福州江阴实船作业统计可视化系统

基于 FastAPI + ECharts 的 Confluence 数据采集与可视化报表系统。

🎯 项目目标

自动采集 Confluence "福州江阴实船作业统计" 页面及其子页面的表格数据, 生成面向团队的 Web 可视化报表。

🏗️ 系统架构

┌─────────────────┐     ┌──────────────────┐     ┌─────────────────┐
│   Confluence    │────▶│   Data Fetcher   │────▶│   Data Parser   │
│     API         │     │   (Confluence    │     │  (Table Extract)│
│                 │     │    Client)       │     │                 │
└─────────────────┘     └──────────────────┘     └─────────────────┘
                                                           │
                                                           ▼
┌─────────────────┐     ┌──────────────────┐     ┌─────────────────┐
│   Web Frontend  │◄────│   FastAPI        │◄────│   Data Store    │
│  (ECharts Viz)  │     │   REST API       │     │  (JSON/Cache)   │
└─────────────────┘     └──────────────────┘     └─────────────────┘

🛠️ 技术栈

  • 后端: Python 3.10+, FastAPI, Uvicorn
  • 前端: HTML5, JavaScript, ECharts 5.x
  • 数据采集: requests, BeautifulSoup4, pandas
  • 缓存: 文件系统缓存JSON

📡 Confluence API 集成

API 端点

端点 描述
GET /rest/api/content/{id} 获取页面内容
GET /rest/api/content/{id}/child/page 获取子页面列表

认证方式

使用 Bearer Token 认证:

headers = {
    "Authorization": "Bearer {token}",
    "Content-Type": "application/json"
}

页面树遍历

async def get_page_tree(page_id: str) -> List[PageNode]:
    """
    递归获取页面及其所有子页面
    """
    children = await fetch_children(page_id)
    tree = []
    for child in children:
        node = PageNode(
            id=child['id'],
            title=child['title'],
            url=child['_links']['webui'],
            children=await get_page_tree(child['id'])
        )
        tree.append(node)
    return tree

表格数据提取

def extract_table_data(html_content: str) -> pd.DataFrame:
    """
    从 Confluence 页面 HTML 中提取表格数据
    """
    soup = BeautifulSoup(html_content, 'html.parser')
    tables = soup.find_all('table', {'class': 'confluenceTable'})
    
    if not tables:
        return pd.DataFrame()
    
    # 使用 pandas 解析第一个表格
    df = pd.read_html(str(tables[0]))[0]
    return df

📊 数据模型

页面元数据

class PageNode(BaseModel):
    id: str
    title: str
    url: str
    children: List['PageNode'] = []
    data: Optional[ShipData] = None

船舶报告数据

class ShipData(BaseModel):
    ship_code: str           # 如 "FZ 361#"
    location: str            # "FZ" = 福州
    ship_number: str         # "361#"
    report_date: date        # 报告日期
    raw_data: Dict           # 原始表格数据

月度统计

class MonthlyStats(BaseModel):
    month: str               # "2026.02"
    page_id: str
    total_ships: int
    ships: List[ShipData]
    summary: Dict            # 汇总统计

🔌 FastAPI API 规范

端点列表

方法 端点 描述
GET /api/health 健康检查
GET /api/pages/tree 获取完整页面树
GET /api/pages/{page_id} 获取指定页面数据
GET /api/monthly/{month} 获取月度统计
GET /api/statistics/summary 获取整体汇总
POST /api/refresh 强制刷新缓存

响应示例

获取页面树

{
  "root_page": {
    "id": "137446574",
    "title": "福州江阴实船作业统计",
    "children": [
      {
        "id": "137446576",
        "title": "2025.06 实船作业统计",
        "children": []
      },
      {
        "id": "161630736",
        "title": "2026.02 实船作业统计",
        "children": [
          {
            "id": "161630738",
            "title": "FZ 361#实船报告2026.02.01",
            "children": []
          }
        ]
      }
    ]
  }
}

获取统计数据

{
  "month": "2026.02",
  "total_ships": 15,
  "ships": [
    {
      "ship_code": "FZ 361#",
      "report_date": "2026-02-01",
      "data": {
        "作业量": "1000吨",
        "作业时长": "8小时"
      }
    }
  ]
}

📈 可视化方案

推荐图表类型

  1. 月度趋势图(折线图)

    • X轴月份2025.06 - 2026.02
    • Y轴作业次数/作业量
  2. 船次分布图(饼图/环形图)

    • 各船次出现频次分布
  3. 日历热力图

    • 展示作业日期分布密度
  4. 船次效率对比(横向柱状图)

    • 比较各船次的平均作业量
  5. 汇总仪表板

    • KPI 卡片:总船次、月均船次、活跃船次数

页面布局

┌─────────────────────────────────────┐
│         关键指标卡片区域            │
├─────────────────┬─────────────────┤
│   月度趋势图     │   船次分布图    │
├─────────────────┴─────────────────┤
│           日历热力图               │
├─────────────────┬─────────────────┤
│   船次对比图     │   数据明细表    │
└─────────────────┴─────────────────┘

ECharts 示例

// 月度趋势图
const trendChart = echarts.init(document.getElementById('trend'));

const option = {
    title: { text: '月度实船作业趋势' },
    xAxis: {
        type: 'category',
        data: ['2025.06', '2025.07', '2025.08', '2025.09', 
               '2025.10', '2025.11', '2025.12', '2026.01', '2026.02']
    },
    yAxis: { type: 'value', name: '作业次数' },
    series: [{
        data: [12, 15, 18, 20, 22, 19, 25, 21, 15],
        type: 'line',
        smooth: true,
        areaStyle: {}
    }]
};

trendChart.setOption(option);

🚀 部署指南

环境配置

创建 .env 文件:

CONFLUENCE_BASE_URL=https://confluence.westwell-lab.com
CONFLUENCE_TOKEN=your_token_here
ROOT_PAGE_ID=137446574
CACHE_DIR=./cache

安装依赖

pip install fastapi uvicorn requests beautifulsoup4 pandas python-dotenv

运行服务

# 开发模式
uvicorn main:app --reload

# 生产模式
uvicorn main:app --host 0.0.0.0 --port 8000

访问应用

  • API 文档: http://localhost:8000/docs
  • 可视化页面: http://localhost:8000/static/index.html

📁 项目结构

project/
├── main.py              # FastAPI 主应用
├── config.py            # 配置管理
├── confluence/
│   ├── __init__.py
│   ├── client.py        # Confluence API 客户端
│   └── parser.py        # 数据解析器
├── models/
│   ├── __init__.py
│   └── schemas.py       # Pydantic 数据模型
├── services/
│   ├── __init__.py
│   ├── cache.py         # 缓存管理
│   └── data_service.py  # 数据服务
├── static/
│   ├── index.html       # 可视化页面
│   ├── css/
│   └── js/
│       └── charts.js    # ECharts 配置
├── cache/               # 缓存文件目录
├── .env                 # 环境变量
└── README.md

🔧 后续扩展

  • 数据导出功能Excel/PDF
  • 定时自动同步
  • 邮件通知
  • 历史数据对比分析
  • 移动端适配

📝 待确认事项

  1. 表格字段:抓取示例页面后确定需要提取的具体字段
  2. 更新频率:是否需要定时同步或仅手动刷新
  3. 权限控制:是否需要用户登录功能
Description
No description provided
Readme 67 KiB
Languages
Python 69%
JavaScript 21.9%
HTML 8.6%
Shell 0.5%