feat: 新增日程面板、复盘页面与 Agent 读写接口
- 日程:单次/每日/每周/每月重复,JSON 存储,月历按优先级着色圆点 + 悬停提示 - 复盘页:可自定义折线图卡片(SVG) + 每日心得总览(按日期/任务展开) - Agent 接口:GET /api/agent/overview 读日程+进度,POST /api/agent/schedules 建日程(PPM_API_TOKEN Bearer 鉴权) - 导出/导入/统计纳入日程与图表;47 项测试全绿
This commit is contained in:
@@ -121,3 +121,59 @@ class PurgeInput(BaseModel):
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
confirmation: str
|
||||
|
||||
|
||||
class ScheduleRecurrence(str, Enum):
|
||||
none = "none"
|
||||
daily = "daily"
|
||||
weekly = "weekly"
|
||||
monthly = "monthly"
|
||||
|
||||
|
||||
class ScheduleInput(BaseModel):
|
||||
model_config = ConfigDict(extra="forbid", str_strip_whitespace=True)
|
||||
|
||||
title: Annotated[str, Field(min_length=1, max_length=120)]
|
||||
description: Annotated[str, Field(max_length=2000)] = ""
|
||||
date: date
|
||||
time: Annotated[str | None, Field(max_length=5)] = None
|
||||
recurrence: ScheduleRecurrence = ScheduleRecurrence.none
|
||||
priority: Annotated[int, Field(ge=1, le=5)] = 3
|
||||
state: Literal["active", "archived"] = "active"
|
||||
|
||||
@field_validator("time")
|
||||
@classmethod
|
||||
def validate_time(cls, value: str | None) -> str | None:
|
||||
if value is None or value == "":
|
||||
return None
|
||||
if len(value) != 5 or value[2] != ":" or not value[:2].isdigit() or not value[3:].isdigit():
|
||||
raise ValueError("时间必须是 HH:MM 格式")
|
||||
hour, minute = int(value[:2]), int(value[3:])
|
||||
if hour > 23 or minute > 59:
|
||||
raise ValueError("时间必须是合法的时分")
|
||||
return value
|
||||
|
||||
|
||||
class ScheduleUpdate(ScheduleInput):
|
||||
expectedVersion: Annotated[int, Field(ge=1)]
|
||||
|
||||
|
||||
class ScheduleCompleteInput(BaseModel):
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
date: date
|
||||
completed: bool = True
|
||||
expectedVersion: Annotated[int, Field(ge=1)]
|
||||
|
||||
|
||||
class ChartInput(BaseModel):
|
||||
model_config = ConfigDict(extra="forbid", str_strip_whitespace=True)
|
||||
|
||||
title: Annotated[str, Field(min_length=1, max_length=80)]
|
||||
taskId: str | None = None
|
||||
metricId: str | None = None
|
||||
days: Annotated[int, Field(ge=7, le=365)] = 30
|
||||
|
||||
|
||||
class ChartUpdate(ChartInput):
|
||||
expectedVersion: Annotated[int, Field(ge=1)]
|
||||
|
||||
Reference in New Issue
Block a user