feat:新增大屏存取发布接口

This commit is contained in:
2026-10-11 08:27:30 -07:00
parent dadd797391
commit afc07ba695
23 changed files with 2672 additions and 36 deletions
+20 -3
View File
@@ -1,9 +1,15 @@
"""会话及对话轮次,用于多轮上下文和后续持久化"""
from datetime import datetime
from typing import Literal
from typing import Annotated, Literal
from pydantic import BaseModel
from pydantic import BaseModel, StringConstraints
from .base import NonBlankString
Title = Annotated[
str, StringConstraints(strip_whitespace=True, min_length=1, max_length=100)
]
class Turn(BaseModel):
@@ -18,6 +24,15 @@ class Turn(BaseModel):
created_at: datetime
class ConversationCreate(BaseModel):
# 会话归属的大屏;不传则不归属任何大屏(兼容旧调用)
screen_id: NonBlankString | None = None
class ConversationRename(BaseModel):
title: Title
class ConversationCreated(BaseModel):
conversation_id: str
@@ -31,9 +46,11 @@ class ConversationSummary(BaseModel):
"""历史会话列表项,只包含已产生对话的会话"""
conversation_id: str
title: str # 取自首轮用户输入,过长时截断
title: str # 用户改过名用改的,否则取自首轮用户输入,过长时截断
screen_id: str | None = None
updated_at: datetime # 最近一轮对话的创建时间
class ConversationList(BaseModel):
conversations: list[ConversationSummary]
total: int # 符合条件的会话总数(不受 limit / offset 影响),管理页翻页用
+5
View File
@@ -212,7 +212,9 @@ class DataFileInfo(BaseModel):
encoding: str | None
size: int
created_at: datetime
# 被已保存的大屏引用时固定为 True,此时 expires_at 是个遥远的占位时间,不会过期
expires_at: datetime
pinned: bool = False
tables: list[DataTableInfo]
warnings: list[ParseWarning]
# 未启用智能分析,或这是功能上线前上传的文件时为空
@@ -229,6 +231,9 @@ class DataFileRecord(DataFileDetail):
tables: list[DataTable]
# 删除只做标记,记录留到过期,会话内的表名不会被新文件重复使用
deleted: bool = False
# 引用这个文件的大屏 ID。非空时文件不过期(expires_at 被推到 PINNED_EXPIRES),
# 最后一个引用消失后重新按保留时长计时
pinned_by: list[str] = Field(default_factory=list)
UploadStatus = Literal["queued", "parsing", "ready", "failed"]
+175
View File
@@ -0,0 +1,175 @@
"""保存的大屏:存储记录与接口模型。页面本身(PageSchema)按原始 JSON 存取,校验见 app/schemas/screen.py"""
from datetime import datetime
from typing import Annotated, Any, Literal
from pydantic import BaseModel, Field, StringConstraints
NAME_MAX_LENGTH = 100
DEFAULT_NAME = "未命名大屏"
ScreenName = Annotated[
str,
StringConstraints(strip_whitespace=True, min_length=1, max_length=NAME_MAX_LENGTH),
]
PublishStatus = Literal["published", "offline"]
ListStatus = Literal["draft", "published", "offline"]
SortField = Literal["updated_at", "created_at", "name"]
class PublishInfo(BaseModel):
"""screens.publish:线上版本的指针,快照本身在 screen_publishes"""
status: PublishStatus
version: int # 当前线上版本号
revision: int # 线上版本是从哪个 revision 发出去的
share_id: str
published_at: datetime
class ScreenSummary(BaseModel):
"""不含页面的大屏记录,列表、元数据更新和线上读取用"""
screen_id: str
owner_id: int
name: str
thumbnail: str | None = None
canvas: dict[str, Any] | None = None
revision: int
created_at: datetime
updated_at: datetime
deleted_at: datetime | None = None
publish: PublishInfo | None = None
class ScreenRecord(ScreenSummary):
page: dict[str, Any]
class PublishEntry(BaseModel):
screen_id: str
version: int
revision: int
published_at: datetime
published_by: int
class PublishSnapshot(PublishEntry):
"""发布快照,只增不改"""
page: dict[str, Any]
# ---- 请求 ----
class ScreenCreate(BaseModel):
name: ScreenName = DEFAULT_NAME
page: dict[str, Any] | None = None
class ScreenSave(BaseModel):
page: dict[str, Any]
revision: int = Field(ge=0)
class ScreenRename(BaseModel):
name: ScreenName
class ScreenPublishRequest(BaseModel):
revision: int = Field(ge=0)
class ScreenCopyRequest(BaseModel):
name: ScreenName | None = None
# ---- 响应 ----
class ScreenCreated(BaseModel):
screen_id: str
revision: int
class PublishBrief(BaseModel):
status: PublishStatus
version: int
share_id: str
published_at: datetime
class ScreenDetail(BaseModel):
screen_id: str
name: str
page: dict[str, Any]
revision: int
updated_at: datetime
publish: PublishBrief | None
class ScreenSaved(BaseModel):
revision: int
updated_at: datetime
class ScreenPublished(BaseModel):
version: int
share_id: str
published_at: datetime
class ScreenListItem(BaseModel):
screen_id: str
name: str
thumbnail_url: str | None
canvas: dict[str, Any] | None
status: ListStatus
has_unpublished_changes: bool
share_id: str | None
updated_at: datetime
published_at: datetime | None
deleted_at: datetime | None
# 在回收站里的大屏,到这个时间会被自动彻底删除
purge_at: datetime | None
class ScreenList(BaseModel):
items: list[ScreenListItem]
total: int
class TrashEmptied(BaseModel):
count: int
class ScreenCopied(BaseModel):
screen_id: str
class ThumbnailResult(BaseModel):
thumbnail_url: str
class PublishHistoryItem(BaseModel):
version: int
revision: int
published_at: datetime
published_by: int
class PublishHistory(BaseModel):
items: list[PublishHistoryItem]
total: int
class ScreenRestored(BaseModel):
revision: int
class PublicScreen(BaseModel):
name: str
page: dict[str, Any]
version: int
published_at: datetime