feat: 添加日历批量操作与客户端时区感知功能,优化前端 UI 交互体验

This commit is contained in:
zl-q
2026-03-17 00:13:41 +08:00
parent d3783522e6
commit c26cdbbc27
27 changed files with 1532 additions and 412 deletions
+48 -2
View File
@@ -3,8 +3,9 @@ from __future__ import annotations
from datetime import datetime
from typing import ClassVar
from uuid import UUID
from zoneinfo import ZoneInfo, ZoneInfoNotFoundError
from pydantic import BaseModel, ConfigDict, EmailStr, Field
from pydantic import BaseModel, ConfigDict, EmailStr, Field, field_validator
from schemas.inbox.messages import (
CalendarContent,
@@ -49,9 +50,27 @@ class ScheduleItemCreateRequest(BaseModel):
description: str | None = Field(default=None, max_length=2000)
start_at: datetime
end_at: datetime | None = None
timezone: str = Field(default="UTC", max_length=50)
timezone: str = Field(..., min_length=1, max_length=50)
metadata: ScheduleItemMetadata | None = None
@field_validator("timezone")
@classmethod
def validate_timezone(cls, value: str) -> str:
try:
ZoneInfo(value)
except ZoneInfoNotFoundError as exc:
raise ValueError("timezone must be a valid IANA timezone") from exc
return value
@field_validator("start_at", "end_at")
@classmethod
def validate_datetime_tzinfo(cls, value: datetime | None) -> datetime | None:
if value is None:
return None
if value.tzinfo is None:
raise ValueError("datetime must include timezone offset")
return value
class ScheduleItemUpdateRequest(BaseModel):
model_config: ClassVar[ConfigDict] = ConfigDict(extra="forbid")
@@ -64,6 +83,26 @@ class ScheduleItemUpdateRequest(BaseModel):
metadata: ScheduleItemMetadata | None = None
status: ScheduleItemStatus | None = None
@field_validator("timezone")
@classmethod
def validate_timezone(cls, value: str | None) -> str | None:
if value is None:
return None
try:
ZoneInfo(value)
except ZoneInfoNotFoundError as exc:
raise ValueError("timezone must be a valid IANA timezone") from exc
return value
@field_validator("start_at", "end_at")
@classmethod
def validate_datetime_tzinfo(cls, value: datetime | None) -> datetime | None:
if value is None:
return None
if value.tzinfo is None:
raise ValueError("datetime must include timezone offset")
return value
class ScheduleItemResponse(BaseModel):
model_config: ClassVar[ConfigDict] = ConfigDict(from_attributes=True)
@@ -99,6 +138,13 @@ class ScheduleItemListRequest(BaseModel):
start_at: datetime
end_at: datetime
@field_validator("start_at", "end_at")
@classmethod
def validate_datetime_tzinfo(cls, value: datetime) -> datetime:
if value.tzinfo is None:
raise ValueError("datetime must include timezone offset")
return value
_PERMISSION_VIEW = 1
_PERMISSION_INVITE = 2