Files
Timeline_Generator/app.py
beabigegg 2d37d23bcf v9.5: 實作標籤完全不重疊算法
- 新增 _calculate_lane_conflicts_v2() 分開返回標籤重疊和線穿框分數
- 修改泳道選擇算法,優先選擇無標籤重疊的泳道
- 兩階段搜尋:優先側別無可用泳道則嘗試另一側
- 增強日誌輸出,顯示標籤範圍和詳細衝突分數

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

158 lines
4.0 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 的絕對路徑
"""
# 開發模式:從專案目錄載入
dev_path = Path(__file__).parent / "frontend" / "static" / "index.html"
if dev_path.exists():
return str(dev_path.absolute())
# 打包模式:從執行檔旁邊載入
bundle_path = Path(sys.executable).parent / "frontend" / "static" / "index.html"
if bundle_path.exists():
return str(bundle_path.absolute())
# 找不到前端檔案
logger.error("找不到前端 HTML 檔案")
raise FileNotFoundError("Frontend index.html not found")
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()