feat: restore source parity and harden agent runtime

This commit is contained in:
2026-06-22 11:17:26 +08:00
parent e33f08277b
commit 0793eb82d6
596 changed files with 168879 additions and 290 deletions
+495
View File
@@ -0,0 +1,495 @@
from typing import Optional, List, Any, Dict
from pydantic import BaseModel, ConfigDict, Field
from app.base_schema import CSTDatetime
# ==================== SmartTable ====================
class SmartTableCreate(BaseModel):
name: str = Field(..., min_length=1, max_length=200, description="表名")
icon: str = Field(default="Grid", max_length=50, description="图标")
description: Optional[str] = Field(None, description="描述")
type: str = Field(default="table", description="类型: table / document")
content: Optional[Dict[str, Any]] = Field(None, description="文档内容(Tiptap JSON), 仅 type=document 时使用")
parent_id: Optional[str] = Field(None, description="父页面ID")
wiki_space_id: Optional[str] = Field(None, description="所属文档库ID")
class SmartTableUpdate(BaseModel):
name: Optional[str] = Field(None, min_length=1, max_length=200, description="表名")
icon: Optional[str] = Field(None, max_length=50, description="图标")
description: Optional[str] = Field(None, description="描述")
active_view_id: Optional[str] = Field(None, description="当前激活视图ID")
content: Optional[Dict[str, Any]] = Field(None, description="文档内容(Tiptap JSON)")
parent_id: Optional[str] = Field(None, description="父页面ID")
class SmartTableMove(BaseModel):
parent_id: Optional[str] = Field(None, description="目标父页面IDnull 表示移到根级")
after_id: Optional[str] = Field(None, description="排在此项之后,null 表示排在同级首位")
class SmartTableResponse(BaseModel):
id: str
name: str
icon: str = "Grid"
description: Optional[str] = None
active_view_id: Optional[str] = None
type: str = "table"
parent_id: Optional[str] = None
wiki_space_id: Optional[str] = None
sort: int = 0
sys_create_datetime: Optional[CSTDatetime] = None
sys_update_datetime: Optional[CSTDatetime] = None
model_config = ConfigDict(from_attributes=True)
class SmartTableSimple(BaseModel):
"""列表简要信息(含 parent_id 以便前端构建树)"""
id: str
name: str
icon: str = "Grid"
type: str = "table"
parent_id: Optional[str] = None
wiki_space_id: Optional[str] = None
sort: int = 0
model_config = ConfigDict(from_attributes=True)
# ==================== SmartField ====================
class SmartFieldCreate(BaseModel):
table_id: Optional[str] = Field(None, description="所属表ID(从URL路径注入)")
name: str = Field(..., min_length=1, max_length=200, description="字段名")
type: str = Field(..., description="字段类型")
width: int = Field(default=150, description="列宽")
visible: bool = Field(default=True, description="是否可见")
required: bool = Field(default=False, description="是否必填")
description: Optional[str] = Field(None, description="描述")
config: Optional[Dict[str, Any]] = Field(default_factory=dict, description="扩展配置")
sort: int = Field(default=0, description="排序")
class SmartFieldUpdate(BaseModel):
name: Optional[str] = Field(None, min_length=1, max_length=200, description="字段名")
type: Optional[str] = Field(None, description="字段类型")
width: Optional[int] = Field(None, description="列宽")
visible: Optional[bool] = Field(None, description="是否可见")
required: Optional[bool] = Field(None, description="是否必填")
description: Optional[str] = Field(None, description="描述")
config: Optional[Dict[str, Any]] = Field(None, description="扩展配置")
sort: Optional[int] = Field(None, description="排序")
class SmartFieldResponse(BaseModel):
id: str
table_id: str
name: str
type: str
width: int = 150
visible: bool = True
required: bool = False
description: Optional[str] = None
config: Optional[Dict[str, Any]] = None
sort: int = 0
sys_create_datetime: Optional[CSTDatetime] = None
sys_update_datetime: Optional[CSTDatetime] = None
model_config = ConfigDict(from_attributes=True)
class SmartFieldReorder(BaseModel):
field_ids: List[str] = Field(..., description="按顺序排列的字段ID列表")
# ==================== SmartRecord ====================
class SmartRecordCreate(BaseModel):
table_id: Optional[str] = Field(None, description="所属表ID(从URL路径注入)")
values: Dict[str, Any] = Field(default_factory=dict, description="字段值映射")
class SmartRecordUpdate(BaseModel):
values: Optional[Dict[str, Any]] = Field(None, description="字段值映射")
class SmartRecordCellUpdate(BaseModel):
"""更新单个单元格"""
field_id: str = Field(..., description="字段ID")
value: Any = Field(None, description="单元格值")
class SmartRecordResponse(BaseModel):
id: str
table_id: str
values: Dict[str, Any] = {}
sys_create_datetime: Optional[CSTDatetime] = None
sys_update_datetime: Optional[CSTDatetime] = None
sys_creator_id: Optional[str] = None
sys_modifier_id: Optional[str] = None
model_config = ConfigDict(from_attributes=True)
class SmartRecordBatchDelete(BaseModel):
ids: List[str] = Field(..., description="要删除的记录ID列表")
class SmartRecordBatchRestore(BaseModel):
ids: List[str] = Field(..., description="要恢复的记录ID列表")
class TrashRecordResponse(BaseModel):
id: str
table_id: str
values: Dict[str, Any] = {}
sys_create_datetime: Optional[CSTDatetime] = None
sys_update_datetime: Optional[CSTDatetime] = None
sys_creator_id: Optional[str] = None
model_config = ConfigDict(from_attributes=True)
class TrashListResponse(BaseModel):
items: List[TrashRecordResponse]
total: int
# ==================== SmartView ====================
class SmartViewCreate(BaseModel):
table_id: Optional[str] = Field(None, description="所属表ID(从URL路径注入)")
name: str = Field(..., min_length=1, max_length=200, description="视图名")
type: str = Field(default="grid", description="视图类型")
config: Optional[Dict[str, Any]] = Field(default_factory=dict, description="视图配置")
sort: int = Field(default=0, description="排序")
class SmartViewUpdate(BaseModel):
name: Optional[str] = Field(None, min_length=1, max_length=200, description="视图名")
type: Optional[str] = Field(None, description="视图类型")
config: Optional[Dict[str, Any]] = Field(None, description="视图配置")
sort: Optional[int] = Field(None, description="排序")
class SmartViewResponse(BaseModel):
id: str
table_id: str
name: str
type: str = "grid"
config: Optional[Dict[str, Any]] = None
sort: int = 0
sys_create_datetime: Optional[CSTDatetime] = None
sys_update_datetime: Optional[CSTDatetime] = None
model_config = ConfigDict(from_attributes=True)
# ==================== Record Query (Server-side filter/sort/search) ====================
class RecordFilterRule(BaseModel):
field_id: str = Field(..., description="字段ID")
operator: str = Field(..., description="操作符: equals, notEquals, contains, notContains, isEmpty, isNotEmpty, greaterThan, lessThan, greaterThanOrEqual, lessThanOrEqual")
value: Any = Field(None, description="筛选值")
class RecordSortRule(BaseModel):
field_id: str = Field(..., description="字段ID")
direction: str = Field(default="asc", description="排序方向: asc / desc")
class RecordQuery(BaseModel):
filters: List[RecordFilterRule] = Field(default_factory=list, description="筛选条件")
filter_logic: str = Field(default="and", description="筛选逻辑: and / or")
sorts: List[RecordSortRule] = Field(default_factory=list, description="排序规则")
search: Optional[str] = Field(None, description="全文搜索关键词")
search_field_ids: Optional[List[str]] = Field(None, description="搜索范围字段ID列表,为空搜索所有文本字段")
group_field_id: Optional[str] = Field(None, description="分组字段ID")
cursor: Optional[str] = Field(None, description="游标(上一页最后一条记录的ID")
limit: int = Field(default=200, ge=1, le=5000, description="每页数量")
class RecordGroupItem(BaseModel):
key: str
label: str
records: List[SmartRecordResponse] = []
class GroupedRecordsResponse(BaseModel):
groups: List[RecordGroupItem]
total: int
class SmartRecordReorder(BaseModel):
record_ids: List[str] = Field(..., description="按顺序排列的记录ID列表")
# ==================== Batch Cell Update ====================
class SmartRecordBatchCellUpdate(BaseModel):
"""批量更新多个单元格"""
cells: Dict[str, Any] = Field(..., description="fieldId->value 映射")
class MultiRecordCellUpdate(BaseModel):
"""单条记录的更新项"""
record_id: str = Field(..., description="记录ID")
cells: Dict[str, Any] = Field(..., description="fieldId->value 映射")
class MultiRecordBatchUpdate(BaseModel):
"""批量更新多条记录的单元格 - 合并为单次事务"""
updates: List[MultiRecordCellUpdate] = Field(..., description="更新列表", max_length=200)
# ==================== Cursor Pagination ====================
class CursorPaginatedRecords(BaseModel):
items: List[SmartRecordResponse]
total: int
next_cursor: Optional[str] = None
has_more: bool = False
# ==================== Full Table Load ====================
# ==================== Link / Lookup / Rollup ====================
class LinkCellUpdate(BaseModel):
"""更新 Link 字段的关联记录"""
record_ids: List[str] = Field(..., description="目标记录ID列表")
class LinkedRecordItem(BaseModel):
"""关联记录摘要"""
id: str
title: str = ""
class RecordSearchResult(BaseModel):
"""搜索目标表记录结果"""
id: str
title: str = ""
class RecordSearchQuery(BaseModel):
"""搜索请求"""
keyword: str = Field(default="", description="搜索关键词")
limit: int = Field(default=20, ge=1, le=100, description="返回数量")
# ==================== Full Table Load ====================
class SmartTableFull(BaseModel):
"""完整表数据(含字段、首页记录、视图)"""
id: str
name: str
icon: str = "Grid"
description: Optional[str] = None
active_view_id: Optional[str] = None
type: str = "table"
parent_id: Optional[str] = None
wiki_space_id: Optional[str] = None
content: Optional[Dict[str, Any]] = None
fields: List[SmartFieldResponse] = []
records: List[SmartRecordResponse] = []
views: List[SmartViewResponse] = []
record_total: int = 0
next_cursor: Optional[str] = None
has_more: bool = False
sys_create_datetime: Optional[CSTDatetime] = None
sys_update_datetime: Optional[CSTDatetime] = None
sys_creator_id: Optional[str] = None
creator_name: Optional[str] = None
creator_avatar: Optional[str] = None
model_config = ConfigDict(from_attributes=True)
# ==================== Comment ====================
class CommentCreate(BaseModel):
content: str = Field(..., min_length=1, max_length=5000, description="评论内容")
mentions: List[str] = Field(default_factory=list, description="被@提及的用户ID列表")
parent_id: Optional[str] = Field(None, description="父评论ID(回复)")
class CommentUpdate(BaseModel):
content: str = Field(..., min_length=1, max_length=5000, description="评论内容")
mentions: List[str] = Field(default_factory=list, description="被@提及的用户ID列表")
class CommentResponse(BaseModel):
id: str
record_id: str
user_id: str
content: str
mentions: List[str] = []
parent_id: Optional[str] = None
sys_create_datetime: Optional[CSTDatetime] = None
sys_update_datetime: Optional[CSTDatetime] = None
user_name: Optional[str] = None
user_avatar: Optional[str] = None
replies: List["CommentResponse"] = []
model_config = ConfigDict(from_attributes=True)
CommentResponse.model_rebuild()
# ==================== Summary / Aggregation ====================
class SummaryRequest(BaseModel):
"""汇总请求:指定字段及聚合方式"""
aggregations: Dict[str, str] = Field(
..., description="fieldId -> aggregation_type 映射,如 {'fld_abc': 'SUM'}"
)
filters: List[RecordFilterRule] = Field(default_factory=list, description="筛选条件")
filter_logic: str = Field(default="and", description="筛选逻辑: and / or")
search: Optional[str] = Field(None, description="搜索关键词")
class SummaryResponse(BaseModel):
"""汇总响应"""
summaries: Dict[str, Any] = Field(
default_factory=dict,
description="fieldId -> 聚合结果,如 {'fld_abc': 12345.67}"
)
total_count: int = 0
# ==================== Document ====================
class DocumentContentUpdate(BaseModel):
"""更新文档内容"""
content: Dict[str, Any] = Field(..., description="Tiptap JSON 文档内容")
# ==================== Document Version ====================
class DocumentVersionCreate(BaseModel):
"""手动创建版本"""
change_summary: Optional[str] = Field(None, max_length=500, description="变更摘要")
class DocumentVersionResponse(BaseModel):
id: str
document_id: str
version: int
title: Optional[str] = None
change_summary: Optional[str] = None
content_size: int = 0
sys_create_datetime: Optional[CSTDatetime] = None
sys_creator_id: Optional[str] = None
creator_name: Optional[str] = None
creator_avatar: Optional[str] = None
model_config = ConfigDict(from_attributes=True)
class DocumentVersionDetail(DocumentVersionResponse):
"""版本详情(含完整内容)"""
content: Dict[str, Any] = {}
class DocumentVersionCompare(BaseModel):
"""版本对比结果"""
version_from: DocumentVersionDetail
version_to: DocumentVersionDetail
# ==================== Document Template ====================
class DocumentTemplateCreate(BaseModel):
name: str = Field(..., min_length=1, max_length=200, description="模板名称")
description: Optional[str] = Field(None, description="模板描述")
icon: str = Field(default="FileText", max_length=50, description="模板图标")
category: str = Field(default="custom", max_length=50, description="分类")
content: Dict[str, Any] = Field(..., description="模板内容(Tiptap JSON)")
preview_image: Optional[str] = Field(None, description="预览图URL")
class DocumentTemplateUpdate(BaseModel):
name: Optional[str] = Field(None, min_length=1, max_length=200, description="模板名称")
description: Optional[str] = Field(None, description="模板描述")
icon: Optional[str] = Field(None, max_length=50, description="模板图标")
category: Optional[str] = Field(None, max_length=50, description="分类")
content: Optional[Dict[str, Any]] = Field(None, description="模板内容(Tiptap JSON)")
preview_image: Optional[str] = Field(None, description="预览图URL")
class DocumentTemplateResponse(BaseModel):
id: str
name: str
description: Optional[str] = None
icon: str = "FileText"
category: str = "custom"
preview_image: Optional[str] = None
is_system: bool = False
use_count: int = 0
sys_create_datetime: Optional[CSTDatetime] = None
sys_update_datetime: Optional[CSTDatetime] = None
sys_creator_id: Optional[str] = None
creator_name: Optional[str] = None
model_config = ConfigDict(from_attributes=True)
class DocumentTemplateDetail(DocumentTemplateResponse):
"""模板详情(含完整内容)"""
content: Dict[str, Any] = {}
# ==================== Wiki Space ====================
class WikiSpaceCreate(BaseModel):
name: str = Field(..., min_length=1, max_length=200, description="文档库名称")
icon: str = Field(default="BookOpen", max_length=50, description="图标")
avatar: Optional[str] = Field(None, description="头像文件ID")
description: Optional[str] = Field(None, description="描述")
cover: Optional[str] = Field(None, description="封面图URL")
category: str = Field(default="default", max_length=50, description="分类标签")
visibility: str = Field(default="private", description="可见性: private/team/public")
class WikiSpaceUpdate(BaseModel):
name: Optional[str] = Field(None, min_length=1, max_length=200, description="文档库名称")
icon: Optional[str] = Field(None, max_length=50, description="图标")
avatar: Optional[str] = Field(None, description="头像文件ID")
description: Optional[str] = Field(None, description="描述")
cover: Optional[str] = Field(None, description="封面图URL")
category: Optional[str] = Field(None, max_length=50, description="分类标签")
visibility: Optional[str] = Field(None, description="可见性: private/team/public")
class WikiSpaceResponse(BaseModel):
id: str
name: str
icon: str = "BookOpen"
avatar: Optional[str] = None
description: Optional[str] = None
cover: Optional[str] = None
category: str = "default"
visibility: str = "private"
sort: int = 0
sys_create_datetime: Optional[CSTDatetime] = None
sys_update_datetime: Optional[CSTDatetime] = None
sys_creator_id: Optional[str] = None
creator_name: Optional[str] = None
model_config = ConfigDict(from_attributes=True)
class WikiSpaceListItem(WikiSpaceResponse):
"""列表项,含文档数量"""
document_count: int = 0
class WikiSpaceDetail(WikiSpaceResponse):
"""详情,含文档列表"""
documents: List[SmartTableSimple] = []