Files
water-management-system/src/api/bi_api.py
T
bot_dev1 61acfd8f8b feat: 实现自助BI看板功能,支持Superset/Metabase集成
- 新增BI模块(src/bi/),包含数据模型、服务和控制器
- 支持数据源管理、图表创建、看板配置
- 实现多图表类型:折线图、柱状图、饼图、散点图、面积图、仪表盘、表格
- 提供REST API(/bi/)和前端API(/bi-api/)接口
- 创建响应式前端界面,支持拖拽和实时数据展示
- 默认包含运营总览、设备管理、安全监控看板
- 支持与Superset和Metabase集成

🤖 Generated with [OpenClaw](https://github.com/robocomp/openclaw)
2026-06-15 12:29:34 +08:00

215 lines
7.9 KiB
Python

"""
BI前端API模块
为前端提供BI相关的API接口,简化前端调用
"""
from fastapi import APIRouter, HTTPException, Query
from typing import List, Optional, Dict, Any
import json
# 创建BI路由器
router = APIRouter(prefix="/bi-api", tags=["BI API"])
@router.get("/dashboards/overview")
async def get_overview_dashboards():
"""获取概览看板数据"""
return {
"dashboards": [
{
"id": "operation_overview",
"name": "水务运营总览",
"description": "水务系统整体运营情况综合看板",
"charts_count": 4,
"is_public": True,
"tags": ["运营", "总览", "综合"]
},
{
"id": "device_management",
"name": "设备管理看板",
"description": "设备状态监控和维护管理",
"charts_count": 1,
"is_public": False,
"tags": ["设备", "管理", "监控"]
},
{
"id": "security_monitoring",
"name": "安全监控看板",
"description": "系统安全和警报监控",
"charts_count": 1,
"is_public": False,
"tags": ["安全", "监控", "警报"]
}
]
}
@router.get("/charts/{chart_id}/data")
async def get_chart_data_frontend(chart_id: str):
"""获取图表数据(前端友好格式)"""
# 这里调用BI服务获取数据,简化前端调用
try:
from ..bi.services import BIService
bi_service = BIService()
data = bi_service.get_chart_data_api(chart_id)
if "error" in data:
raise HTTPException(status_code=404, detail=data["error"])
# 格式化为前端友好的数据格式
formatted_data = {
"chartId": chart_id,
"chartName": data.get("chart_name", ""),
"chartType": data.get("chart_type", ""),
"data": data.get("data", []),
"options": data.get("options", {}),
"columns": data.get("columns", [])
}
return formatted_data
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.get("/dashboards/{dashboard_id}/data")
async def get_dashboard_data_frontend(dashboard_id: str):
"""获取看板数据(前端友好格式)"""
try:
from ..bi.services import BIService
bi_service = BIService()
data = bi_service.get_dashboard_data_api(dashboard_id)
if "error" in data:
raise HTTPException(status_code=404, detail=data["error"])
return data
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.get("/charts/types")
async def get_chart_types():
"""获取支持的图表类型"""
return {
"line": {"name": "折线图", "description": "适合展示趋势数据"},
"bar": {"name": "柱状图", "description": "适合展示分类数据"},
"pie": {"name": "饼图", "description": "适合展示比例数据"},
"scatter": {"name": "散点图", "description": "适合展示关系数据"},
"area": {"name": "面积图", "description": "适合展示累计数据"},
"gauge": {"name": "仪表盘", "description": "适合展示进度或状态"},
"table": {"name": "表格", "description": "适合展示详细数据"},
"heatmap": {"name": "热力图", "description": "适合展示密度数据"}
}
@router.get("/data-sources/types")
async def get_data_source_types():
"""获取支持的数据源类型"""
return {
"sensor_data": {"name": "传感器数据", "description": "IoT传感器实时和历史数据"},
"device_data": {"name": "设备数据", "description": "设备状态和配置信息"},
"alert_data": {"name": "警报数据", "description": "系统警报和通知记录"},
"system_stats": {"name": "系统统计", "description": "系统运行性能统计"},
"batch_data": {"name": "批量数据", "description": "批量导入的数据"}
}
@router.get("/search")
async def search_bi_objects(keyword: str = Query(..., description="搜索关键词")):
"""搜索BI对象(图表和看板)"""
try:
from ..bi.services import BIService
bi_service = BIService()
# 搜索图表
charts = bi_service.search_charts(keyword)
charts_data = [chart.to_dict() for chart in charts]
# 搜索看板
dashboards = bi_service.search_dashboards(keyword)
dashboards_data = [dashboard.to_dict() for dashboard in dashboards]
return {
"charts": charts_data,
"dashboards": dashboards_data,
"total": len(charts_data) + len(dashboards_data)
}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.get("/popular-tags")
async def get_popular_tags():
"""获取热门标签"""
try:
from ..bi.services import BIService
bi_service = BIService()
# 收集所有标签
all_tags = set()
for chart in bi_service.get_all_charts():
all_tags.update(chart.tags)
for dashboard in bi_service.get_all_dashboards():
all_tags.update(dashboard.tags)
# 返回热门标签(按字母排序)
return {"tags": sorted(list(all_tags))}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.get("/quick-stats")
async def get_quick_stats():
"""获取快速统计信息"""
try:
from ..bi.services import BIService
bi_service = BIService()
charts = bi_service.get_all_charts()
dashboards = bi_service.get_all_dashboards()
public_dashboards = bi_service.get_public_dashboards()
# 统计图表类型分布
chart_type_stats = {}
for chart in charts:
chart_type = chart.chart_type.value
chart_type_stats[chart_type] = chart_type_stats.get(chart_type, 0) + 1
# 统计标签分布
tag_stats = {}
for chart in charts:
for tag in chart.tags:
tag_stats[tag] = tag_stats.get(tag, 0) + 1
for dashboard in dashboards:
for tag in dashboard.tags:
tag_stats[tag] = tag_stats.get(tag, 0) + 1
return {
"total_charts": len(charts),
"total_dashboards": len(dashboards),
"public_dashboards": len(public_dashboards),
"chart_types": chart_type_stats,
"popular_tags": dict(sorted(tag_stats.items(), key=lambda x: x[1], reverse=True)[:10])
}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.get("/chart-suggestions")
async def get_chart_suggestions():
"""获取图表建议"""
return {
"suggestions": [
{
"id": "flow_analysis",
"name": "流量分析建议",
"description": "基于历史流量数据,分析流量趋势和异常",
"charts": ["flow_trend", "flow_comparison"],
"tags": ["流量", "分析", "趋势"]
},
{
"id": "device_performance",
"name": "设备性能分析",
"description": "分析设备运行状态和性能指标",
"charts": ["device_status_distribution", "device_uptime"],
"tags": ["设备", "性能", "分析"]
},
{
"id": "security_dashboard",
"name": "安全监控看板",
"description": "集中监控系统安全和警报信息",
"charts": ["alert_level_stats", "alert_trend"],
"tags": ["安全", "监控", "警报"]
}
]
}