Files
Timeline_Generator/backend/schemas.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

258 lines
7.3 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.

"""
資料模型定義 (Data Schemas)
本模組定義 TimeLine Designer 所有資料結構。
遵循 Pydantic BaseModel 進行嚴格型別驗證。
Author: AI Agent
Version: 1.0.0
DocID: SDD-SCHEMA-001
Rationale: 實現 SDD.md 第2節定義的資料模型
"""
from datetime import datetime
from typing import Optional, Literal, List
from pydantic import BaseModel, Field, field_validator
from enum import Enum
class EventType(str, Enum):
"""事件類型枚舉"""
POINT = "point" # 時間點事件
RANGE = "range" # 時間區間事件
MILESTONE = "milestone" # 里程碑
class Event(BaseModel):
"""
時間軸事件模型
對應 SDD.md - 2. 資料模型 - Event
用於表示時間軸上的單一事件或時間區間。
"""
id: str = Field(..., description="事件唯一識別碼")
title: str = Field(..., min_length=1, max_length=200, description="事件標題")
start: datetime = Field(..., description="開始時間")
end: Optional[datetime] = Field(None, description="結束時間(可選)")
group: Optional[str] = Field(None, description="事件群組/分類")
description: Optional[str] = Field(None, max_length=1000, description="事件詳細描述")
color: str = Field(default='#3B82F6', pattern=r'^#[0-9A-Fa-f]{6}$', description="事件顏色HEX格式")
event_type: EventType = Field(EventType.POINT, description="事件類型")
@field_validator('end')
@classmethod
def validate_end_after_start(cls, end, info):
"""驗證結束時間必須晚於開始時間"""
if end and info.data.get('start') and end < info.data['start']:
raise ValueError('結束時間必須晚於開始時間')
return end
class Config:
json_schema_extra = {
"example": {
"id": "evt-001",
"title": "專案啟動",
"start": "2024-01-01T09:00:00",
"end": "2024-01-01T17:00:00",
"group": "Phase 1",
"description": "專案正式啟動會議",
"color": "#3B82F6",
"event_type": "range"
}
}
class ThemeStyle(str, Enum):
"""主題樣式枚舉"""
MODERN = "modern"
CLASSIC = "classic"
MINIMAL = "minimal"
CORPORATE = "corporate"
class TimelineConfig(BaseModel):
"""
時間軸配置模型
對應 SDD.md - 2. 資料模型 - TimelineConfig
控制時間軸的顯示方式與視覺樣式。
"""
direction: Literal['horizontal', 'vertical'] = Field(
'horizontal',
description="時間軸方向"
)
theme: ThemeStyle = Field(
ThemeStyle.MODERN,
description="視覺主題"
)
show_grid: bool = Field(
True,
description="是否顯示網格線"
)
show_tooltip: bool = Field(
True,
description="是否顯示提示訊息"
)
enable_zoom: bool = Field(
True,
description="是否啟用縮放功能"
)
enable_drag: bool = Field(
True,
description="是否啟用拖曳功能"
)
class Config:
json_schema_extra = {
"example": {
"direction": "horizontal",
"theme": "modern",
"show_grid": True,
"show_tooltip": True,
"enable_zoom": True,
"enable_drag": True
}
}
class ExportFormat(str, Enum):
"""匯出格式枚舉"""
PNG = "png"
PDF = "pdf"
SVG = "svg"
class ExportOptions(BaseModel):
"""
匯出選項模型
對應 SDD.md - 2. 資料模型 - ExportOptions
控制時間軸圖檔的匯出格式與品質。
"""
fmt: ExportFormat = Field(..., description="匯出格式")
dpi: int = Field(
300,
ge=72,
le=600,
description="解析度DPI"
)
width: Optional[int] = Field(
1920,
ge=800,
le=4096,
description="圖片寬度(像素)"
)
height: Optional[int] = Field(
1080,
ge=600,
le=4096,
description="圖片高度(像素)"
)
transparent_background: bool = Field(
False,
description="是否使用透明背景"
)
class Config:
json_schema_extra = {
"example": {
"fmt": "pdf",
"dpi": 300,
"width": 1920,
"height": 1080,
"transparent_background": False
}
}
class Theme(BaseModel):
"""
主題定義模型
用於 /themes API 回傳主題列表。
"""
name: str = Field(..., description="主題名稱")
style: ThemeStyle = Field(..., description="主題樣式識別碼")
primary_color: str = Field(..., pattern=r'^#[0-9A-Fa-f]{6}$', description="主要顏色")
background_color: str = Field(..., pattern=r'^#[0-9A-Fa-f]{6}$', description="背景顏色")
text_color: str = Field(..., pattern=r'^#[0-9A-Fa-f]{6}$', description="文字顏色")
class Config:
json_schema_extra = {
"example": {
"name": "現代風格",
"style": "modern",
"primary_color": "#3B82F6",
"background_color": "#FFFFFF",
"text_color": "#1F2937"
}
}
class ImportResult(BaseModel):
"""
匯入結果模型
用於 /import API 回傳匯入結果。
"""
success: bool = Field(..., description="是否成功")
events: List[Event] = Field(default_factory=list, description="成功匯入的事件列表")
errors: List[str] = Field(default_factory=list, description="錯誤訊息列表")
total_rows: int = Field(0, description="總行數")
imported_count: int = Field(0, description="成功匯入數量")
class Config:
json_schema_extra = {
"example": {
"success": True,
"events": [],
"errors": [],
"total_rows": 100,
"imported_count": 98
}
}
class RenderResult(BaseModel):
"""
渲染結果模型
用於 /render API 回傳 Plotly JSON 格式的時間軸資料。
"""
success: bool = Field(..., description="是否成功")
data: dict = Field(..., description="Plotly 圖表資料JSON格式")
layout: dict = Field(..., description="Plotly 佈局設定")
config: dict = Field(default_factory=dict, description="Plotly 配置")
class Config:
json_schema_extra = {
"example": {
"success": True,
"data": {},
"layout": {},
"config": {}
}
}
class APIResponse(BaseModel):
"""
通用 API 回應模型
用於標準化 API 回應格式,提供一致的錯誤處理。
"""
success: bool = Field(..., description="操作是否成功")
message: str = Field("", description="回應訊息")
data: Optional[dict] = Field(None, description="回應資料")
error_code: Optional[str] = Field(None, description="錯誤代碼(如有)")
class Config:
json_schema_extra = {
"example": {
"success": True,
"message": "操作成功",
"data": None,
"error_code": None
}
}