diff --git a/backend/app/__pycache__/__init__.cpython-311.pyc b/backend/app/__pycache__/__init__.cpython-311.pyc index 5a1aa0e9..33194c8f 100644 Binary files a/backend/app/__pycache__/__init__.cpython-311.pyc and b/backend/app/__pycache__/__init__.cpython-311.pyc differ diff --git a/backend/app/__pycache__/main.cpython-311.pyc b/backend/app/__pycache__/main.cpython-311.pyc index 75ff4f7c..e53e5438 100644 Binary files a/backend/app/__pycache__/main.cpython-311.pyc and b/backend/app/__pycache__/main.cpython-311.pyc differ diff --git a/backend/app/api/__pycache__/main.cpython-311.pyc b/backend/app/api/__pycache__/main.cpython-311.pyc index 8e7cecd4..23b54aea 100644 Binary files a/backend/app/api/__pycache__/main.cpython-311.pyc and b/backend/app/api/__pycache__/main.cpython-311.pyc differ diff --git a/backend/app/api/main.py b/backend/app/api/main.py index adfc9494..1cd69b55 100644 --- a/backend/app/api/main.py +++ b/backend/app/api/main.py @@ -10,6 +10,7 @@ from app.api.v1 import ( alerts, settings, collected_data, + visualization, ) api_router = APIRouter() @@ -25,3 +26,4 @@ api_router.include_router(tasks.router, prefix="/tasks", tags=["tasks"]) api_router.include_router(dashboard.router, prefix="/dashboard", tags=["dashboard"]) api_router.include_router(alerts.router, prefix="/alerts", tags=["alerts"]) api_router.include_router(settings.router, prefix="/settings", tags=["settings"]) +api_router.include_router(visualization.router, prefix="/visualization", tags=["visualization"]) diff --git a/backend/app/api/v1/__pycache__/alerts.cpython-311.pyc b/backend/app/api/v1/__pycache__/alerts.cpython-311.pyc index 6b0e999e..c606af7a 100644 Binary files a/backend/app/api/v1/__pycache__/alerts.cpython-311.pyc and b/backend/app/api/v1/__pycache__/alerts.cpython-311.pyc differ diff --git a/backend/app/api/v1/__pycache__/auth.cpython-311.pyc b/backend/app/api/v1/__pycache__/auth.cpython-311.pyc index 71d837af..699cf5f0 100644 Binary files a/backend/app/api/v1/__pycache__/auth.cpython-311.pyc and b/backend/app/api/v1/__pycache__/auth.cpython-311.pyc differ diff --git a/backend/app/api/v1/__pycache__/dashboard.cpython-311.pyc b/backend/app/api/v1/__pycache__/dashboard.cpython-311.pyc index c80fc59d..974f474e 100644 Binary files a/backend/app/api/v1/__pycache__/dashboard.cpython-311.pyc and b/backend/app/api/v1/__pycache__/dashboard.cpython-311.pyc differ diff --git a/backend/app/api/v1/__pycache__/datasource_config.cpython-311.pyc b/backend/app/api/v1/__pycache__/datasource_config.cpython-311.pyc index 9e7ebb87..6a93cbe3 100644 Binary files a/backend/app/api/v1/__pycache__/datasource_config.cpython-311.pyc and b/backend/app/api/v1/__pycache__/datasource_config.cpython-311.pyc differ diff --git a/backend/app/api/v1/__pycache__/datasources.cpython-311.pyc b/backend/app/api/v1/__pycache__/datasources.cpython-311.pyc index 67060121..15068795 100644 Binary files a/backend/app/api/v1/__pycache__/datasources.cpython-311.pyc and b/backend/app/api/v1/__pycache__/datasources.cpython-311.pyc differ diff --git a/backend/app/api/v1/__pycache__/settings.cpython-311.pyc b/backend/app/api/v1/__pycache__/settings.cpython-311.pyc index 91425adb..82c3167c 100644 Binary files a/backend/app/api/v1/__pycache__/settings.cpython-311.pyc and b/backend/app/api/v1/__pycache__/settings.cpython-311.pyc differ diff --git a/backend/app/api/v1/__pycache__/tasks.cpython-311.pyc b/backend/app/api/v1/__pycache__/tasks.cpython-311.pyc index b64e1456..a14444f5 100644 Binary files a/backend/app/api/v1/__pycache__/tasks.cpython-311.pyc and b/backend/app/api/v1/__pycache__/tasks.cpython-311.pyc differ diff --git a/backend/app/api/v1/__pycache__/users.cpython-311.pyc b/backend/app/api/v1/__pycache__/users.cpython-311.pyc index 0d054840..e965fc02 100644 Binary files a/backend/app/api/v1/__pycache__/users.cpython-311.pyc and b/backend/app/api/v1/__pycache__/users.cpython-311.pyc differ diff --git a/backend/app/api/v1/__pycache__/websocket.cpython-311.pyc b/backend/app/api/v1/__pycache__/websocket.cpython-311.pyc index 2fbd1b49..01422a72 100644 Binary files a/backend/app/api/v1/__pycache__/websocket.cpython-311.pyc and b/backend/app/api/v1/__pycache__/websocket.cpython-311.pyc differ diff --git a/backend/app/api/v1/visualization.py b/backend/app/api/v1/visualization.py new file mode 100644 index 00000000..5e77a2d8 --- /dev/null +++ b/backend/app/api/v1/visualization.py @@ -0,0 +1,81 @@ +"""Visualization API - GeoJSON endpoints for 3D Earth display""" + +from fastapi import APIRouter, HTTPException +import httpx + +router = APIRouter() + +CABLE_DATA_URL = "https://services.arcgis.com/6DIQcwlPy8knb6sg/arcgis/rest/services/SubmarineCables/FeatureServer/2/query?where=1%3D1&outFields=*&returnGeometry=true&f=geojson" +LANDING_POINT_CSV_URL = "https://data.apps.fao.org/catalog/dataset/1b75ff21-92f2-4b96-9b7b-98e8aa65ad5d/resource/b6071077-d1d4-4e97-aa00-42e902847c87/download/landing-point-geo.csv" + + +@router.get("/geo/cables") +async def get_cables_geojson(): + """获取海底电缆 GeoJSON 数据 (LineString)""" + try: + async with httpx.AsyncClient(timeout=60.0) as client: + response = await client.get(CABLE_DATA_URL) + response.raise_for_status() + return response.json() + except httpx.HTTPError as e: + raise HTTPException(status_code=502, detail=f"Failed to fetch cable data: {str(e)}") + except Exception as e: + raise HTTPException(status_code=500, detail=f"Internal error: {str(e)}") + + +@router.get("/geo/landing-points") +async def get_landing_points_geojson(): + """获取登陆点 GeoJSON 数据 (Point)""" + try: + async with httpx.AsyncClient(timeout=60.0) as client: + response = await client.get(LANDING_POINT_CSV_URL) + response.raise_for_status() + + lines = response.text.strip().split("\n") + if not lines: + raise HTTPException(status_code=500, detail="Empty CSV data") + + features = [] + for line in lines[1:]: + if not line.strip(): + continue + parts = line.split(",") + if len(parts) >= 4: + try: + lon = float(parts[0]) + lat = float(parts[1]) + feature_id = parts[2] + name = parts[3].strip('"') + is_tbd = parts[4].strip() == "true" if len(parts) > 4 else False + + features.append( + { + "type": "Feature", + "geometry": {"type": "Point", "coordinates": [lon, lat]}, + "properties": {"id": feature_id, "name": name, "is_tbd": is_tbd}, + } + ) + except (ValueError, IndexError): + continue + + return {"type": "FeatureCollection", "features": features} + except httpx.HTTPError as e: + raise HTTPException(status_code=502, detail=f"Failed to fetch landing point data: {str(e)}") + except Exception as e: + raise HTTPException(status_code=500, detail=f"Internal error: {str(e)}") + + +@router.get("/geo/all") +async def get_all_geojson(): + """获取所有可视化数据 (电缆 + 登陆点)""" + cables = await get_cables_geojson() + points = await get_landing_points_geojson() + + return { + "cables": cables, + "landing_points": points, + "stats": { + "cable_count": len(cables.get("features", [])) if cables else 0, + "landing_point_count": len(points.get("features", [])) if points else 0, + }, + } diff --git a/backend/app/core/__pycache__/cache.cpython-311.pyc b/backend/app/core/__pycache__/cache.cpython-311.pyc index 6aa72734..75c2a6b5 100644 Binary files a/backend/app/core/__pycache__/cache.cpython-311.pyc and b/backend/app/core/__pycache__/cache.cpython-311.pyc differ diff --git a/backend/app/core/__pycache__/config.cpython-311.pyc b/backend/app/core/__pycache__/config.cpython-311.pyc index e4257685..3750f72c 100644 Binary files a/backend/app/core/__pycache__/config.cpython-311.pyc and b/backend/app/core/__pycache__/config.cpython-311.pyc differ diff --git a/backend/app/core/__pycache__/security.cpython-311.pyc b/backend/app/core/__pycache__/security.cpython-311.pyc index 734d1415..fc8ad15a 100644 Binary files a/backend/app/core/__pycache__/security.cpython-311.pyc and b/backend/app/core/__pycache__/security.cpython-311.pyc differ diff --git a/backend/app/core/config.py b/backend/app/core/config.py index 262ebee6..207150e5 100644 --- a/backend/app/core/config.py +++ b/backend/app/core/config.py @@ -19,7 +19,7 @@ class Settings(BaseSettings): POSTGRES_USER: str = "postgres" POSTGRES_PASSWORD: str = "postgres" POSTGRES_DB: str = "planet_db" - DATABASE_URL: str = f"postgresql+asyncpg://postgres:postgres@postgres:5432/planet_db" + DATABASE_URL: str = f"postgresql+asyncpg://postgres:postgres@localhost:5432/planet_db" REDIS_SERVER: str = "localhost" REDIS_PORT: int = 6379 diff --git a/backend/app/core/websocket/__pycache__/__init__.cpython-311.pyc b/backend/app/core/websocket/__pycache__/__init__.cpython-311.pyc index 6e056838..4268ffaf 100644 Binary files a/backend/app/core/websocket/__pycache__/__init__.cpython-311.pyc and b/backend/app/core/websocket/__pycache__/__init__.cpython-311.pyc differ diff --git a/backend/app/core/websocket/__pycache__/broadcaster.cpython-311.pyc b/backend/app/core/websocket/__pycache__/broadcaster.cpython-311.pyc index adddfc8e..81d6675b 100644 Binary files a/backend/app/core/websocket/__pycache__/broadcaster.cpython-311.pyc and b/backend/app/core/websocket/__pycache__/broadcaster.cpython-311.pyc differ diff --git a/backend/app/core/websocket/__pycache__/manager.cpython-311.pyc b/backend/app/core/websocket/__pycache__/manager.cpython-311.pyc index 44cf77b2..eb6685ca 100644 Binary files a/backend/app/core/websocket/__pycache__/manager.cpython-311.pyc and b/backend/app/core/websocket/__pycache__/manager.cpython-311.pyc differ diff --git a/backend/app/db/__pycache__/session.cpython-311.pyc b/backend/app/db/__pycache__/session.cpython-311.pyc index 778e188a..f72450db 100644 Binary files a/backend/app/db/__pycache__/session.cpython-311.pyc and b/backend/app/db/__pycache__/session.cpython-311.pyc differ diff --git a/backend/app/models/__pycache__/__init__.cpython-311.pyc b/backend/app/models/__pycache__/__init__.cpython-311.pyc index e47ed076..719c282f 100644 Binary files a/backend/app/models/__pycache__/__init__.cpython-311.pyc and b/backend/app/models/__pycache__/__init__.cpython-311.pyc differ diff --git a/backend/app/models/__pycache__/alert.cpython-311.pyc b/backend/app/models/__pycache__/alert.cpython-311.pyc index 26857dd1..3b72bfdd 100644 Binary files a/backend/app/models/__pycache__/alert.cpython-311.pyc and b/backend/app/models/__pycache__/alert.cpython-311.pyc differ diff --git a/backend/app/models/__pycache__/collected_data.cpython-311.pyc b/backend/app/models/__pycache__/collected_data.cpython-311.pyc index b021f2c0..6c121a6f 100644 Binary files a/backend/app/models/__pycache__/collected_data.cpython-311.pyc and b/backend/app/models/__pycache__/collected_data.cpython-311.pyc differ diff --git a/backend/app/models/__pycache__/datasource.cpython-311.pyc b/backend/app/models/__pycache__/datasource.cpython-311.pyc index 7d599130..03af9413 100644 Binary files a/backend/app/models/__pycache__/datasource.cpython-311.pyc and b/backend/app/models/__pycache__/datasource.cpython-311.pyc differ diff --git a/backend/app/models/__pycache__/datasource_config.cpython-311.pyc b/backend/app/models/__pycache__/datasource_config.cpython-311.pyc index 67016aff..d61e3a53 100644 Binary files a/backend/app/models/__pycache__/datasource_config.cpython-311.pyc and b/backend/app/models/__pycache__/datasource_config.cpython-311.pyc differ diff --git a/backend/app/models/__pycache__/gpu_cluster.cpython-311.pyc b/backend/app/models/__pycache__/gpu_cluster.cpython-311.pyc index e9259dae..1fc110c6 100644 Binary files a/backend/app/models/__pycache__/gpu_cluster.cpython-311.pyc and b/backend/app/models/__pycache__/gpu_cluster.cpython-311.pyc differ diff --git a/backend/app/models/__pycache__/task.cpython-311.pyc b/backend/app/models/__pycache__/task.cpython-311.pyc index 6661912e..cd7514be 100644 Binary files a/backend/app/models/__pycache__/task.cpython-311.pyc and b/backend/app/models/__pycache__/task.cpython-311.pyc differ diff --git a/backend/app/models/__pycache__/user.cpython-311.pyc b/backend/app/models/__pycache__/user.cpython-311.pyc index 6d46f373..de76069f 100644 Binary files a/backend/app/models/__pycache__/user.cpython-311.pyc and b/backend/app/models/__pycache__/user.cpython-311.pyc differ diff --git a/backend/app/schemas/__pycache__/token.cpython-311.pyc b/backend/app/schemas/__pycache__/token.cpython-311.pyc index beaa5f1a..3da9401f 100644 Binary files a/backend/app/schemas/__pycache__/token.cpython-311.pyc and b/backend/app/schemas/__pycache__/token.cpython-311.pyc differ diff --git a/backend/app/schemas/__pycache__/user.cpython-311.pyc b/backend/app/schemas/__pycache__/user.cpython-311.pyc index 45c00a23..bd1346e2 100644 Binary files a/backend/app/schemas/__pycache__/user.cpython-311.pyc and b/backend/app/schemas/__pycache__/user.cpython-311.pyc differ diff --git a/backend/app/services/__pycache__/scheduler.cpython-311.pyc b/backend/app/services/__pycache__/scheduler.cpython-311.pyc index e4fe298d..b4e49b24 100644 Binary files a/backend/app/services/__pycache__/scheduler.cpython-311.pyc and b/backend/app/services/__pycache__/scheduler.cpython-311.pyc differ diff --git a/backend/app/services/collectors/__pycache__/__init__.cpython-311.pyc b/backend/app/services/collectors/__pycache__/__init__.cpython-311.pyc index e427cf84..3c1d87e6 100644 Binary files a/backend/app/services/collectors/__pycache__/__init__.cpython-311.pyc and b/backend/app/services/collectors/__pycache__/__init__.cpython-311.pyc differ diff --git a/backend/app/services/collectors/__pycache__/base.cpython-311.pyc b/backend/app/services/collectors/__pycache__/base.cpython-311.pyc index 84809512..e49fbf33 100644 Binary files a/backend/app/services/collectors/__pycache__/base.cpython-311.pyc and b/backend/app/services/collectors/__pycache__/base.cpython-311.pyc differ diff --git a/backend/app/services/collectors/__pycache__/cloudflare.cpython-311.pyc b/backend/app/services/collectors/__pycache__/cloudflare.cpython-311.pyc index a38263fd..91cc5bda 100644 Binary files a/backend/app/services/collectors/__pycache__/cloudflare.cpython-311.pyc and b/backend/app/services/collectors/__pycache__/cloudflare.cpython-311.pyc differ diff --git a/backend/app/services/collectors/__pycache__/epoch_ai.cpython-311.pyc b/backend/app/services/collectors/__pycache__/epoch_ai.cpython-311.pyc index e5ae1d96..2adaa303 100644 Binary files a/backend/app/services/collectors/__pycache__/epoch_ai.cpython-311.pyc and b/backend/app/services/collectors/__pycache__/epoch_ai.cpython-311.pyc differ diff --git a/backend/app/services/collectors/__pycache__/huggingface.cpython-311.pyc b/backend/app/services/collectors/__pycache__/huggingface.cpython-311.pyc index 12e972ac..34a3ca0b 100644 Binary files a/backend/app/services/collectors/__pycache__/huggingface.cpython-311.pyc and b/backend/app/services/collectors/__pycache__/huggingface.cpython-311.pyc differ diff --git a/backend/app/services/collectors/__pycache__/peeringdb.cpython-311.pyc b/backend/app/services/collectors/__pycache__/peeringdb.cpython-311.pyc index 8fbac080..7a5d11f0 100644 Binary files a/backend/app/services/collectors/__pycache__/peeringdb.cpython-311.pyc and b/backend/app/services/collectors/__pycache__/peeringdb.cpython-311.pyc differ diff --git a/backend/app/services/collectors/__pycache__/registry.cpython-311.pyc b/backend/app/services/collectors/__pycache__/registry.cpython-311.pyc index 9e9e8aed..b6657fb3 100644 Binary files a/backend/app/services/collectors/__pycache__/registry.cpython-311.pyc and b/backend/app/services/collectors/__pycache__/registry.cpython-311.pyc differ diff --git a/backend/app/services/collectors/__pycache__/telegeography.cpython-311.pyc b/backend/app/services/collectors/__pycache__/telegeography.cpython-311.pyc index 3c7994fd..28660327 100644 Binary files a/backend/app/services/collectors/__pycache__/telegeography.cpython-311.pyc and b/backend/app/services/collectors/__pycache__/telegeography.cpython-311.pyc differ diff --git a/backend/app/services/collectors/__pycache__/top500.cpython-311.pyc b/backend/app/services/collectors/__pycache__/top500.cpython-311.pyc index dc561146..64e2c9d3 100644 Binary files a/backend/app/services/collectors/__pycache__/top500.cpython-311.pyc and b/backend/app/services/collectors/__pycache__/top500.cpython-311.pyc differ diff --git a/backend/scripts/create_admin.py b/backend/scripts/create_admin.py new file mode 100644 index 00000000..c9ca713d --- /dev/null +++ b/backend/scripts/create_admin.py @@ -0,0 +1,39 @@ +import asyncio +import sys + +sys.path.insert(0, ".") + +from app.db.session import async_session_factory +from app.models.user import User +from app.core.security import get_password_hash + + +async def create_admin(): + async with async_session_factory() as session: + # 检查用户是否已存在 + from sqlalchemy import select + + result = await session.execute(select(User).where(User.username == "linkong")) + existing_user = result.scalar_one_or_none() + + if existing_user: + print(f"用户 linkong 已存在,更新密码...") + existing_user.set_password("LK12345678") + existing_user.role = "super_admin" + else: + print("创建管理员用户...") + user = User( + username="linkong", + email="linkong@example.com", + password_hash=get_password_hash("LK12345678"), + role="super_admin", + is_active=True, + ) + session.add(user) + + await session.commit() + print("完成!") + + +if __name__ == "__main__": + asyncio.run(create_admin()) diff --git a/earth/3dearthmult.html b/earth/3dearthmult.html new file mode 100644 index 00000000..df28cc52 --- /dev/null +++ b/earth/3dearthmult.html @@ -0,0 +1,1912 @@ + + +
+ + +