feat: v3.1 대시보드 추가 (React + FastAPI)
Media Engine Control Panel — 6탭 웹 대시보드 [백엔드] FastAPI (dashboard/backend/) - server.py: 포트 8080, CORS, React SPA 서빙 - api_overview.py: KPI 카드 + 파이프라인 상태 + 활동 로그 - api_content.py: 칸반 보드 + 승인/거부 + 수동 트리거 - api_analytics.py: 방문자 추이 + 플랫폼/코너별 성과 - api_novels.py: 소설 목록/생성/에피소드 관리 - api_settings.py: engine.json CRUD - api_connections.py: AI 서비스 연결 관리 + 키 저장 - api_tools.py: 기능별 AI 도구 선택 - api_cost.py: 구독 현황 + API 사용량 추적 - api_logs.py: 시스템 로그 필터/검색 [프론트엔드] React + Vite + Tailwind + Recharts (dashboard/frontend/) - Overview: KPI 카드 + 파이프라인 + 코너별 바차트 + 활동 로그 - Content: 4열 칸반 보드 + 상세 모달 + 승인/거부 - Analytics: LineChart 방문자 추이 + 플랫폼별 성과 - Novel: 소설 목록 + 에피소드 테이블 + 새 소설 생성 폼 - Settings: 5개 서브탭 (AI연결/도구선택/배포채널/품질/비용관리) - Logs: 필터/검색 시스템 로그 뷰어 [디자인] CNN 다크+골드 테마 - 배경 #0a0a0d + 액센트 #c8a84e - 모바일 반응형 (Tailscale 외부 접속 대응) [실행] - dashboard/start.bat 더블클릭 → http://localhost:8080 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
78
dashboard/backend/server.py
Normal file
78
dashboard/backend/server.py
Normal file
@@ -0,0 +1,78 @@
|
||||
"""
|
||||
dashboard/backend/server.py
|
||||
미디어 엔진 컨트롤 패널 — FastAPI 메인 서버
|
||||
|
||||
실행: uvicorn dashboard.backend.server:app --port 8080
|
||||
또는: python -m uvicorn dashboard.backend.server:app --port 8080 --reload
|
||||
"""
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
from fastapi import FastAPI
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
from fastapi.responses import FileResponse
|
||||
|
||||
from dashboard.backend import (
|
||||
api_overview,
|
||||
api_content,
|
||||
api_analytics,
|
||||
api_novels,
|
||||
api_settings,
|
||||
api_connections,
|
||||
api_tools,
|
||||
api_cost,
|
||||
api_logs,
|
||||
)
|
||||
|
||||
app = FastAPI(title="The 4th Path — Control Panel", version="1.0.0")
|
||||
|
||||
# ── CORS ──────────────────────────────────────────────────────────────────────
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=[
|
||||
"http://localhost:5173",
|
||||
"http://localhost:8080",
|
||||
"http://127.0.0.1:5173",
|
||||
"http://127.0.0.1:8080",
|
||||
],
|
||||
allow_credentials=True,
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
)
|
||||
|
||||
# ── API 라우터 등록 ────────────────────────────────────────────────────────────
|
||||
app.include_router(api_overview.router, prefix="/api")
|
||||
app.include_router(api_content.router, prefix="/api")
|
||||
app.include_router(api_analytics.router, prefix="/api")
|
||||
app.include_router(api_novels.router, prefix="/api")
|
||||
app.include_router(api_settings.router, prefix="/api")
|
||||
app.include_router(api_connections.router, prefix="/api")
|
||||
app.include_router(api_tools.router, prefix="/api")
|
||||
app.include_router(api_cost.router, prefix="/api")
|
||||
app.include_router(api_logs.router, prefix="/api")
|
||||
|
||||
@app.get("/api/health")
|
||||
async def health():
|
||||
return {"status": "ok", "service": "The 4th Path Control Panel"}
|
||||
|
||||
|
||||
# ── 정적 파일 서빙 (프론트엔드 빌드 결과) — API 라우터보다 나중에 등록 ──────────
|
||||
FRONTEND_DIST = Path(__file__).parent.parent / "frontend" / "dist"
|
||||
|
||||
if FRONTEND_DIST.exists():
|
||||
assets_dir = FRONTEND_DIST / "assets"
|
||||
if assets_dir.exists():
|
||||
app.mount("/assets", StaticFiles(directory=str(assets_dir)), name="assets")
|
||||
|
||||
@app.get("/", include_in_schema=False)
|
||||
@app.get("/{full_path:path}", include_in_schema=False)
|
||||
async def serve_spa(full_path: str = ""):
|
||||
# API 경로는 위 라우터가 처리 — 여기는 SPA 라우팅용
|
||||
if full_path.startswith("api/"):
|
||||
from fastapi.responses import JSONResponse
|
||||
return JSONResponse({"detail": "Not Found"}, status_code=404)
|
||||
index = FRONTEND_DIST / "index.html"
|
||||
if index.exists():
|
||||
return FileResponse(str(index))
|
||||
return {"status": "frontend not built — run: npm run build"}
|
||||
Reference in New Issue
Block a user