Files
ai-agent-admin/backend-fastapi/core/file_manager/schema.py
T
2026-06-08 18:14:59 +08:00

278 lines
12 KiB
Python

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
文件管理Schema
"""
from datetime import datetime
from typing import Optional, List, Any
from pydantic import BaseModel, ConfigDict, Field
from app.base_schema import CSTDatetime
# ==================== 文件管理 Schema ====================
class FileManagerBase(BaseModel):
"""文件管理基础Schema"""
name: str = Field(..., description="文件/文件夹名称")
type: str = Field(default='file', description="类型: file/folder")
parent_id: Optional[str] = Field(None, description="父文件夹ID")
is_public: bool = Field(default=False, description="是否公开")
class FileManagerCreate(FileManagerBase):
"""创建文件记录Schema(内部使用)"""
path: str = Field(default='', description="文件路径")
size: int = Field(default=0, description="文件大小")
file_ext: Optional[str] = Field(None, description="文件扩展名")
mime_type: Optional[str] = Field(None, description="MIME类型")
storage_type: str = Field(default='local', description="存储类型")
storage_path: str = Field(default='', description="存储路径")
url: Optional[str] = Field(None, description="访问URL")
md5: Optional[str] = Field(None, description="文件MD5")
class FileManagerUpdate(BaseModel):
"""更新文件记录Schema"""
name: Optional[str] = None
is_public: Optional[bool] = None
class FileManagerResponse(BaseModel):
"""文件管理响应Schema"""
id: str
name: str
type: str = Field(alias="file_type")
parent_id: Optional[str] = None
parent_name: Optional[str] = None
path: str
size: int = Field(alias="file_size")
file_ext: Optional[str] = None
mime_type: Optional[str] = None
storage_type: str
storage_path: str
url: Optional[str] = None
thumbnail_url: Optional[str] = None
md5: Optional[str] = None
is_public: bool
download_count: int
is_system: bool = False
source: Optional[str] = None
sys_creator_id: Optional[str] = None
has_children: bool = False
updated_time: Optional[str] = None
sys_create_datetime: Optional[CSTDatetime] = None
sys_update_datetime: Optional[CSTDatetime] = None
model_config = ConfigDict(from_attributes=True, populate_by_name=True)
class FileManagerSimpleResponse(BaseModel):
"""文件管理简单响应Schema"""
id: str
name: str
type: str
size: int
sys_create_datetime: Optional[CSTDatetime] = None
mime_type: Optional[str] = None
model_config = ConfigDict(from_attributes=True)
# ==================== 文件夹操作 Schema ====================
class CreateFolderIn(BaseModel):
"""创建文件夹输入Schema"""
name: str = Field(..., description="文件夹名称")
parent_id: Optional[str] = Field(None, alias="parentId", description="父文件夹ID")
model_config = ConfigDict(populate_by_name=True)
class MoveItemsIn(BaseModel):
"""移动文件/文件夹输入Schema"""
ids: List[str] = Field(..., description="要移动的文件/文件夹ID列表")
target_folder_id: Optional[str] = Field(None, alias="targetFolderId", description="目标文件夹ID")
model_config = ConfigDict(populate_by_name=True)
class RenameItemIn(BaseModel):
"""重命名输入Schema"""
name: str = Field(..., description="新名称")
class BatchDeleteIn(BaseModel):
"""批量删除输入Schema"""
ids: List[str] = Field(..., description="要删除的文件/文件夹ID列表")
# ==================== 存储配置 Schema ====================
class FileStorageConfigResponse(BaseModel):
"""文件存储配置响应Schema"""
storage_type: str = Field(default='local', alias="storageType", description="存储类型")
local_base_path: Optional[str] = Field(None, alias="localBasePath", description="本地存储路径")
oss_endpoint: Optional[str] = Field(None, alias="ossEndpoint", description="OSS端点")
oss_access_key_id: Optional[str] = Field(None, alias="ossAccessKeyId", description="OSS访问密钥ID")
oss_bucket_name: Optional[str] = Field(None, alias="ossBucketName", description="OSS存储桶名称")
minio_endpoint: Optional[str] = Field(None, alias="minioEndpoint", description="Minio端点")
minio_bucket_name: Optional[str] = Field(None, alias="minioBucketName", description="Minio存储桶名称")
azure_account_name: Optional[str] = Field(None, alias="azureAccountName", description="Azure存储账户名称")
azure_container_name: Optional[str] = Field(None, alias="azureContainerName", description="Azure容器名称")
model_config = ConfigDict(populate_by_name=True)
class FileStorageConfigUpdate(BaseModel):
"""更新存储配置Schema"""
storage_type: str = Field(default='local', alias="storageType", description="存储类型")
local_base_path: Optional[str] = Field(None, alias="localBasePath")
oss_endpoint: Optional[str] = Field(None, alias="ossEndpoint")
oss_access_key_id: Optional[str] = Field(None, alias="ossAccessKeyId")
oss_access_key_secret: Optional[str] = Field(None, alias="ossAccessKeySecret")
oss_bucket_name: Optional[str] = Field(None, alias="ossBucketName")
minio_endpoint: Optional[str] = Field(None, alias="minioEndpoint")
minio_access_key: Optional[str] = Field(None, alias="minioAccessKey")
minio_secret_key: Optional[str] = Field(None, alias="minioSecretKey")
minio_bucket_name: Optional[str] = Field(None, alias="minioBucketName")
azure_account_name: Optional[str] = Field(None, alias="azureAccountName")
azure_account_key: Optional[str] = Field(None, alias="azureAccountKey")
azure_container_name: Optional[str] = Field(None, alias="azureContainerName")
model_config = ConfigDict(populate_by_name=True)
# ==================== 分块上传 Schema ====================
class InitChunkUploadIn(BaseModel):
"""初始化分块上传输入Schema"""
filename: str = Field(..., description="文件名")
total_size: int = Field(..., alias="totalSize", description="文件总大小(字节)")
chunk_size: int = Field(default=5 * 1024 * 1024, alias="chunkSize", description="分块大小(字节),默认5MB")
parent_id: Optional[str] = Field(None, alias="parentId", description="父文件夹ID")
is_public: bool = Field(default=False, alias="isPublic", description="是否公开")
file_hash: Optional[str] = Field(None, alias="fileHash", description="文件MD5哈希,用于秒传")
model_config = ConfigDict(populate_by_name=True)
class InitChunkUploadOut(BaseModel):
"""初始化分块上传输出Schema"""
upload_id: str = Field(..., alias="uploadId", description="上传ID")
chunk_size: int = Field(..., alias="chunkSize", description="分块大小")
total_chunks: int = Field(..., alias="totalChunks", description="总分块数")
uploaded_chunks: List[int] = Field(default=[], alias="uploadedChunks", description="已上传的分块索引列表")
file_exists: bool = Field(default=False, alias="fileExists", description="文件是否已存在(秒传)")
file_id: Optional[str] = Field(None, alias="fileId", description="如果文件已存在,返回文件ID")
model_config = ConfigDict(populate_by_name=True)
class UploadChunkOut(BaseModel):
"""上传分块输出Schema"""
chunk_index: int = Field(..., alias="chunkIndex", description="分块索引")
uploaded: bool = Field(..., description="是否上传成功")
model_config = ConfigDict(populate_by_name=True)
class MergeChunksIn(BaseModel):
"""合并分块输入Schema"""
upload_id: str = Field(..., alias="uploadId", description="上传ID")
model_config = ConfigDict(populate_by_name=True)
class ChunkUploadStatusOut(BaseModel):
"""分块上传状态输出Schema"""
upload_id: str = Field(..., alias="uploadId", description="上传ID")
filename: str = Field(..., description="文件名")
total_size: int = Field(..., alias="totalSize", description="文件总大小")
total_chunks: int = Field(..., alias="totalChunks", description="总分块数")
uploaded_chunks: List[int] = Field(..., alias="uploadedChunks", description="已上传的分块索引")
completed: bool = Field(..., description="是否完成上传")
model_config = ConfigDict(populate_by_name=True)
# ==================== 文件URL Schema ====================
class FileUrlResponse(BaseModel):
"""文件URL响应Schema"""
url: str = Field(..., description="文件访问URL")
class BatchFileUrlsResponse(BaseModel):
"""批量文件URL响应Schema"""
urls: dict = Field(..., description="文件ID到URL的映射")
# ==================== 临时访问令牌 Schema ====================
class CreateAccessTokenIn(BaseModel):
"""创建临时访问令牌输入Schema"""
file_id: str = Field(..., alias="fileId", description="文件ID")
expires_in: int = Field(default=3600, alias="expiresIn", description="过期时间(秒),默认1小时")
model_config = ConfigDict(populate_by_name=True)
class AccessTokenResponse(BaseModel):
"""临时访问令牌响应Schema"""
token: str = Field(..., description="临时访问令牌")
expires_at: CSTDatetime = Field(..., alias="expiresAt", description="过期时间")
file_id: str = Field(..., alias="fileId", description="文件ID")
model_config = ConfigDict(populate_by_name=True)
class AccessTokenUrlResponse(BaseModel):
"""带令牌的文件URL响应Schema"""
url: str = Field(..., description="带临时令牌的文件访问URL")
token: str = Field(..., description="临时访问令牌")
expires_at: CSTDatetime = Field(..., alias="expiresAt", description="过期时间")
model_config = ConfigDict(populate_by_name=True)
# ==================== AI OCR 识别 Schema ====================
class OcrFieldMapping(BaseModel):
"""OCR字段映射配置"""
source: str = Field(..., description="Function返回的字段名")
target: str = Field(..., description="表单字段名")
transform: Optional[str] = Field(None, description="转换规则")
class OcrSchemaField(BaseModel):
"""OCR结构化输出字段定义(与LLM节点SchemaField一致)"""
name: str = Field(..., description="字段名")
type: str = Field(default="string", description="字段类型: string/number/integer/boolean/array/object")
description: str = Field(default="", description="字段描述")
required: bool = Field(default=False, description="是否必填")
items: Optional['OcrSchemaField'] = Field(None, description="array类型的元素定义")
properties: Optional[List['OcrSchemaField']] = Field(None, description="object类型的子属性")
enum: Optional[List[str]] = Field(None, description="枚举值(仅string类型)")
default: Optional[Any] = Field(None, description="默认值")
class OcrRecognizeRequest(BaseModel):
"""OCR智能识别请求Schema"""
file_id: str = Field(..., alias="fileId", description="文件ID")
output_schema: Optional[List[OcrSchemaField]] = Field(None, alias="outputSchema", description="结构化输出字段定义")
prompt: Optional[str] = Field(None, description="自定义提示词")
model_config = ConfigDict(populate_by_name=True)
class OcrRecognizeResponse(BaseModel):
"""OCR智能识别响应Schema"""
success: bool = Field(..., description="是否成功")
raw_text: Optional[str] = Field(None, alias="rawText", description="原始识别文字")
extracted_data: Optional[dict] = Field(None, alias="extractedData", description="提取的结构化数据")
error: Optional[str] = Field(None, description="错误信息")
model_config = ConfigDict(populate_by_name=True)