Files
Timeline_Generator/app.py
beabigegg ad9ba59fdf 更新 app.py:修正前端路徑指向 React
變更:
- 前端路徑從 frontend/static/ 更新為 frontend-react/dist/
- 添加更詳細的錯誤提示(npm run build)
- 添加註解說明推薦使用 start_dev.bat 進行開發
- 配合清理後的專案結構(已刪除舊 frontend 目錄)

🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-06 11:44:00 +08:00

166 lines
4.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
TimeLine Designer - PyWebview 主程式
本程式整合 FastAPI 後端與 HTML 前端,提供桌面應用介面。
Author: AI Agent
Version: 1.0.0
DocID: SDD-APP-001
Rationale: 實現 SDD.md 定義的 PyWebview Host 架構
"""
import webview
import threading
import uvicorn
import logging
import sys
from pathlib import Path
# 設定日誌
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
class TimelineDesignerApp:
"""
TimeLine Designer 應用程式類別
負責啟動 FastAPI 後端與 PyWebview 前端。
"""
def __init__(self):
self.api_port = 8000
self.api_host = "127.0.0.1"
self.frontend_path = self._get_frontend_path()
def _get_frontend_path(self) -> str:
"""
取得前端 HTML 檔案路徑
Returns:
前端 index.html 的絕對路徑
"""
# 開發模式:使用 React 開發伺服器
# 注意:需要先執行 `npm run dev` 啟動 React 前端
# PyWebview 模式已不推薦使用,建議使用 start_dev.bat 啟動前後端分離模式
# React 打包後的前端檔案
react_dist_path = Path(__file__).parent / "frontend-react" / "dist" / "index.html"
if react_dist_path.exists():
logger.info("使用 React 打包後的前端")
return str(react_dist_path.absolute())
# 打包模式:從執行檔旁邊載入
bundle_path = Path(sys.executable).parent / "frontend-react" / "dist" / "index.html"
if bundle_path.exists():
return str(bundle_path.absolute())
# 找不到前端檔案
logger.error("找不到前端 HTML 檔案")
logger.error("請執行以下命令建置前端:")
logger.error(" cd frontend-react")
logger.error(" npm run build")
raise FileNotFoundError("Frontend index.html not found. Please run 'npm run build' in frontend-react/")
def start_api_server(self):
"""
啟動 FastAPI 後端伺服器
在獨立執行緒中運行,避免阻塞主程式。
"""
try:
from backend.main import app
logger.info(f"正在啟動 API 伺服器於 http://{self.api_host}:{self.api_port}")
# 設定 uvicorn
config = uvicorn.Config(
app,
host=self.api_host,
port=self.api_port,
log_level="info"
)
server = uvicorn.Server(config)
server.run()
except Exception as e:
logger.error(f"API 伺服器啟動失敗: {str(e)}")
raise
def start_gui(self):
"""
啟動 PyWebview GUI
在主執行緒中運行。
"""
try:
logger.info("正在啟動 GUI 視窗")
# 建立視窗
window = webview.create_window(
title='TimeLine Designer',
url=self.frontend_path,
width=1400,
height=900,
resizable=True,
fullscreen=False,
min_size=(1024, 768),
)
logger.info("GUI 視窗已建立")
# 啟動 webview這會阻塞直到視窗關閉
webview.start(debug=True)
logger.info("GUI 視窗已關閉")
except Exception as e:
logger.error(f"GUI 啟動失敗: {str(e)}")
raise
def run(self):
"""
執行應用程式
啟動順序:
1. 在背景執行緒啟動 FastAPI 伺服器
2. 在主執行緒啟動 PyWebview GUI
"""
logger.info("=== TimeLine Designer 啟動中 ===")
# 在背景執行緒啟動 API 伺服器
api_thread = threading.Thread(target=self.start_api_server, daemon=True)
api_thread.start()
# 等待 API 伺服器啟動
import time
logger.info("等待 API 伺服器啟動...")
time.sleep(2)
# 在主執行緒啟動 GUI
self.start_gui()
logger.info("=== TimeLine Designer 已關閉 ===")
def main():
"""
應用程式入口點
"""
try:
app = TimelineDesignerApp()
app.run()
except KeyboardInterrupt:
logger.info("使用者中斷程式")
sys.exit(0)
except Exception as e:
logger.error(f"應用程式錯誤: {str(e)}")
sys.exit(1)
if __name__ == "__main__":
main()