Files
Task_Reporter/app/main.py
egg 92834dbe0e feat: Migrate to MySQL and add unified environment configuration
## Database Migration (SQLite → MySQL)
- Add Alembic migration framework
- Add 'tr_' prefix to all tables to avoid conflicts in shared database
- Remove SQLite support, use MySQL exclusively
- Add pymysql driver dependency
- Change ad_token column to Text type for long JWT tokens

## Unified Environment Configuration
- Centralize all hardcoded settings to environment variables
- Backend: Extend Settings class in app/core/config.py
- Frontend: Use Vite environment variables (import.meta.env)
- Docker: Move credentials to environment variables
- Update .env.example files with comprehensive documentation

## Test Organization
- Move root-level test files to tests/ directory:
  - test_chat_room.py → tests/test_chat_room.py
  - test_websocket.py → tests/test_websocket.py
  - test_realtime_implementation.py → tests/test_realtime_implementation.py
- Fix path references in test_realtime_implementation.py

Breaking Changes:
- CORS now requires explicit origins (no more wildcard)
- All database tables renamed with 'tr_' prefix
- SQLite no longer supported

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-07 14:15:11 +08:00

116 lines
3.6 KiB
Python

"""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.modules.auth import router as auth_router
from app.modules.auth.users_router import router as users_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
from app.modules.report_generation import router as report_generation_router
# Frontend build directory
FRONTEND_DIR = Path(__file__).parent.parent / "frontend" / "dist"
settings = get_settings()
# Database tables are managed by Alembic migrations
# Run: alembic upgrade head
# Initialize FastAPI app
app = FastAPI(
title="Task Reporter API",
description="Production Line Incident Response System - 生產線異常即時反應系統",
version="1.0.0",
debug=settings.DEBUG,
)
# CORS middleware - origins configured via CORS_ORIGINS environment variable
app.add_middleware(
CORSMiddleware,
allow_origins=settings.get_cors_origins(),
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Authentication middleware (applies to all /api routes except login/logout)
app.middleware("http")(auth_middleware)
# Include routers
app.include_router(auth_router)
app.include_router(users_router)
app.include_router(chat_room_router)
app.include_router(realtime_router)
app.include_router(file_storage_router)
app.include_router(report_generation_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("/api/health")
async def health_check():
"""Health check for monitoring"""
return {
"status": "healthy",
"service": "Task Reporter API",
"version": "1.0.0",
}
# 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"
)