"""Main FastAPI application 生產線異常即時反應系統 (Task Reporter) """ 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 app.core.config import get_settings from app.core.database import engine, Base from app.modules.auth import router as auth_router from app.modules.auth.middleware import auth_middleware from app.modules.chat_room import router as chat_room_router from app.modules.chat_room.services.template_service import template_service from app.modules.realtime import router as realtime_router from app.modules.file_storage import router as file_storage_router # Frontend build directory FRONTEND_DIR = Path(__file__).parent.parent / "frontend" / "dist" settings = get_settings() # Create database tables Base.metadata.create_all(bind=engine) # Initialize FastAPI app app = FastAPI( title="Task Reporter API", description="Production Line Incident Response System - 生產線異常即時反應系統", version="1.0.0", debug=settings.DEBUG, ) # CORS middleware (adjust for production) app.add_middleware( CORSMiddleware, allow_origins=["*"], # TODO: Restrict in production allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # Authentication middleware (applies to all routes except login/logout) # Note: Commented out for now to allow testing without auth # app.middleware("http")(auth_middleware) # Include routers app.include_router(auth_router) app.include_router(chat_room_router) app.include_router(realtime_router) app.include_router(file_storage_router) @app.on_event("startup") async def startup_event(): """Initialize application on startup""" from app.core.database import SessionLocal from app.core.minio_client import initialize_bucket import logging logger = logging.getLogger(__name__) # Initialize default templates db = SessionLocal() try: template_service.initialize_default_templates(db) finally: db.close() # Initialize MinIO bucket try: if initialize_bucket(): logger.info("MinIO bucket initialized successfully") else: logger.warning("MinIO bucket initialization failed - file uploads may not work") except Exception as e: logger.warning(f"MinIO connection failed: {e} - file uploads will be unavailable") @app.get("/") async def root(): """Health check endpoint""" return { "status": "ok", "service": "Task Reporter API", "version": "1.0.0", "description": "生產線異常即時反應系統", } @app.get("/health") async def health_check(): """Health check for monitoring""" return {"status": "healthy"} # Serve frontend static files (only if build exists) if FRONTEND_DIR.exists(): # Mount static assets (JS, CSS, images) app.mount("/assets", StaticFiles(directory=FRONTEND_DIR / "assets"), name="static") @app.get("/{full_path:path}") async def serve_spa(full_path: str): """Serve the React SPA for all non-API routes""" # Try to serve the exact file if it exists file_path = FRONTEND_DIR / full_path if file_path.exists() and file_path.is_file(): return FileResponse(file_path) # Otherwise serve index.html for client-side routing return FileResponse(FRONTEND_DIR / "index.html") if __name__ == "__main__": import uvicorn uvicorn.run( "app.main:app", host=settings.HOST, port=settings.PORT, reload=settings.DEBUG, log_level="info" )