WebUI后端整体重构
This commit is contained in:
109
src/webui/schemas/__init__.py
Normal file
109
src/webui/schemas/__init__.py
Normal file
@@ -0,0 +1,109 @@
|
||||
"""WebUI Schemas - Pydantic models for API requests and responses."""
|
||||
|
||||
# Auth schemas
|
||||
from .auth import (
|
||||
TokenVerifyRequest,
|
||||
TokenVerifyResponse,
|
||||
TokenUpdateRequest,
|
||||
TokenUpdateResponse,
|
||||
TokenRegenerateResponse,
|
||||
FirstSetupStatusResponse,
|
||||
CompleteSetupResponse,
|
||||
ResetSetupResponse,
|
||||
)
|
||||
|
||||
# Statistics schemas
|
||||
from .statistics import (
|
||||
StatisticsSummary,
|
||||
ModelStatistics,
|
||||
TimeSeriesData,
|
||||
DashboardData,
|
||||
)
|
||||
|
||||
# Emoji schemas
|
||||
from .emoji import (
|
||||
EmojiResponse,
|
||||
EmojiListResponse,
|
||||
EmojiDetailResponse,
|
||||
EmojiUpdateRequest,
|
||||
EmojiUpdateResponse,
|
||||
EmojiDeleteResponse,
|
||||
BatchDeleteRequest,
|
||||
BatchDeleteResponse,
|
||||
EmojiUploadResponse,
|
||||
ThumbnailCacheStatsResponse,
|
||||
ThumbnailCleanupResponse,
|
||||
ThumbnailPreheatResponse,
|
||||
)
|
||||
|
||||
# Chat schemas
|
||||
from .chat import (
|
||||
VirtualIdentityConfig,
|
||||
ChatHistoryMessage,
|
||||
)
|
||||
|
||||
# Plugin schemas
|
||||
from .plugin import (
|
||||
FetchRawFileRequest,
|
||||
FetchRawFileResponse,
|
||||
CloneRepositoryRequest,
|
||||
CloneRepositoryResponse,
|
||||
MirrorConfigResponse,
|
||||
AvailableMirrorsResponse,
|
||||
AddMirrorRequest,
|
||||
UpdateMirrorRequest,
|
||||
GitStatusResponse,
|
||||
InstallPluginRequest,
|
||||
VersionResponse,
|
||||
UninstallPluginRequest,
|
||||
UpdatePluginRequest,
|
||||
UpdatePluginConfigRequest,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
# Auth
|
||||
"TokenVerifyRequest",
|
||||
"TokenVerifyResponse",
|
||||
"TokenUpdateRequest",
|
||||
"TokenUpdateResponse",
|
||||
"TokenRegenerateResponse",
|
||||
"FirstSetupStatusResponse",
|
||||
"CompleteSetupResponse",
|
||||
"ResetSetupResponse",
|
||||
# Statistics
|
||||
"StatisticsSummary",
|
||||
"ModelStatistics",
|
||||
"TimeSeriesData",
|
||||
"DashboardData",
|
||||
# Emoji
|
||||
"EmojiResponse",
|
||||
"EmojiListResponse",
|
||||
"EmojiDetailResponse",
|
||||
"EmojiUpdateRequest",
|
||||
"EmojiUpdateResponse",
|
||||
"EmojiDeleteResponse",
|
||||
"BatchDeleteRequest",
|
||||
"BatchDeleteResponse",
|
||||
"EmojiUploadResponse",
|
||||
"ThumbnailCacheStatsResponse",
|
||||
"ThumbnailCleanupResponse",
|
||||
"ThumbnailPreheatResponse",
|
||||
# Chat
|
||||
"VirtualIdentityConfig",
|
||||
"ChatHistoryMessage",
|
||||
# Plugin
|
||||
"FetchRawFileRequest",
|
||||
"FetchRawFileResponse",
|
||||
"CloneRepositoryRequest",
|
||||
"CloneRepositoryResponse",
|
||||
"MirrorConfigResponse",
|
||||
"AvailableMirrorsResponse",
|
||||
"AddMirrorRequest",
|
||||
"UpdateMirrorRequest",
|
||||
"GitStatusResponse",
|
||||
"InstallPluginRequest",
|
||||
"VersionResponse",
|
||||
"UninstallPluginRequest",
|
||||
"UpdatePluginRequest",
|
||||
"UpdatePluginConfigRequest",
|
||||
]
|
||||
41
src/webui/schemas/auth.py
Normal file
41
src/webui/schemas/auth.py
Normal file
@@ -0,0 +1,41 @@
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
class TokenVerifyRequest(BaseModel):
|
||||
token: str = Field(..., description="访问令牌")
|
||||
|
||||
|
||||
class TokenVerifyResponse(BaseModel):
|
||||
valid: bool = Field(..., description="Token 是否有效")
|
||||
message: str = Field(..., description="验证结果消息")
|
||||
is_first_setup: bool = Field(False, description="是否为首次设置")
|
||||
|
||||
|
||||
class TokenUpdateRequest(BaseModel):
|
||||
new_token: str = Field(..., description="新的访问令牌", min_length=10)
|
||||
|
||||
|
||||
class TokenUpdateResponse(BaseModel):
|
||||
success: bool = Field(..., description="是否更新成功")
|
||||
message: str = Field(..., description="更新结果消息")
|
||||
|
||||
|
||||
class TokenRegenerateResponse(BaseModel):
|
||||
success: bool = Field(..., description="是否生成成功")
|
||||
token: str = Field(..., description="新生成的令牌")
|
||||
message: str = Field(..., description="生成结果消息")
|
||||
|
||||
|
||||
class FirstSetupStatusResponse(BaseModel):
|
||||
is_first_setup: bool = Field(..., description="是否为首次配置")
|
||||
message: str = Field(..., description="状态消息")
|
||||
|
||||
|
||||
class CompleteSetupResponse(BaseModel):
|
||||
success: bool = Field(..., description="是否成功")
|
||||
message: str = Field(..., description="结果消息")
|
||||
|
||||
|
||||
class ResetSetupResponse(BaseModel):
|
||||
success: bool = Field(..., description="是否成功")
|
||||
message: str = Field(..., description="结果消息")
|
||||
26
src/webui/schemas/chat.py
Normal file
26
src/webui/schemas/chat.py
Normal file
@@ -0,0 +1,26 @@
|
||||
from pydantic import BaseModel
|
||||
from typing import Optional
|
||||
|
||||
|
||||
class VirtualIdentityConfig(BaseModel):
|
||||
"""虚拟身份配置"""
|
||||
|
||||
enabled: bool = False
|
||||
platform: Optional[str] = None
|
||||
person_id: Optional[str] = None
|
||||
user_id: Optional[str] = None
|
||||
user_nickname: Optional[str] = None
|
||||
group_id: Optional[str] = None
|
||||
group_name: Optional[str] = None
|
||||
|
||||
|
||||
class ChatHistoryMessage(BaseModel):
|
||||
"""聊天历史消息"""
|
||||
|
||||
id: str
|
||||
type: str # 'user' | 'bot' | 'system'
|
||||
content: str
|
||||
timestamp: float
|
||||
sender_name: str
|
||||
sender_id: Optional[str] = None
|
||||
is_bot: bool = False
|
||||
115
src/webui/schemas/emoji.py
Normal file
115
src/webui/schemas/emoji.py
Normal file
@@ -0,0 +1,115 @@
|
||||
from pydantic import BaseModel
|
||||
from typing import Optional, List
|
||||
|
||||
|
||||
class EmojiResponse(BaseModel):
|
||||
"""表情包响应"""
|
||||
|
||||
id: int
|
||||
full_path: str
|
||||
format: str
|
||||
emoji_hash: str
|
||||
description: str
|
||||
query_count: int
|
||||
is_registered: bool
|
||||
is_banned: bool
|
||||
emotion: Optional[str]
|
||||
record_time: float
|
||||
register_time: Optional[float]
|
||||
usage_count: int
|
||||
last_used_time: Optional[float]
|
||||
|
||||
|
||||
class EmojiListResponse(BaseModel):
|
||||
"""表情包列表响应"""
|
||||
|
||||
success: bool
|
||||
total: int
|
||||
page: int
|
||||
page_size: int
|
||||
data: List[EmojiResponse]
|
||||
|
||||
|
||||
class EmojiDetailResponse(BaseModel):
|
||||
"""表情包详情响应"""
|
||||
|
||||
success: bool
|
||||
data: EmojiResponse
|
||||
|
||||
|
||||
class EmojiUpdateRequest(BaseModel):
|
||||
"""表情包更新请求"""
|
||||
|
||||
description: Optional[str] = None
|
||||
is_registered: Optional[bool] = None
|
||||
is_banned: Optional[bool] = None
|
||||
emotion: Optional[str] = None
|
||||
|
||||
|
||||
class EmojiUpdateResponse(BaseModel):
|
||||
"""表情包更新响应"""
|
||||
|
||||
success: bool
|
||||
message: str
|
||||
data: Optional[EmojiResponse] = None
|
||||
|
||||
|
||||
class EmojiDeleteResponse(BaseModel):
|
||||
"""表情包删除响应"""
|
||||
|
||||
success: bool
|
||||
message: str
|
||||
|
||||
|
||||
class BatchDeleteRequest(BaseModel):
|
||||
"""批量删除请求"""
|
||||
|
||||
emoji_ids: List[int]
|
||||
|
||||
|
||||
class BatchDeleteResponse(BaseModel):
|
||||
"""批量删除响应"""
|
||||
|
||||
success: bool
|
||||
message: str
|
||||
deleted_count: int
|
||||
failed_count: int
|
||||
failed_ids: List[int] = []
|
||||
|
||||
|
||||
class EmojiUploadResponse(BaseModel):
|
||||
"""表情包上传响应"""
|
||||
|
||||
success: bool
|
||||
message: str
|
||||
data: Optional[EmojiResponse] = None
|
||||
|
||||
|
||||
class ThumbnailCacheStatsResponse(BaseModel):
|
||||
"""缩略图缓存统计响应"""
|
||||
|
||||
success: bool
|
||||
cache_dir: str
|
||||
total_count: int
|
||||
total_size_mb: float
|
||||
emoji_count: int
|
||||
coverage_percent: float
|
||||
|
||||
|
||||
class ThumbnailCleanupResponse(BaseModel):
|
||||
"""缩略图清理响应"""
|
||||
|
||||
success: bool
|
||||
message: str
|
||||
cleaned_count: int
|
||||
kept_count: int
|
||||
|
||||
|
||||
class ThumbnailPreheatResponse(BaseModel):
|
||||
"""缩略图预热响应"""
|
||||
|
||||
success: bool
|
||||
message: str
|
||||
generated_count: int
|
||||
skipped_count: int
|
||||
failed_count: int
|
||||
135
src/webui/schemas/plugin.py
Normal file
135
src/webui/schemas/plugin.py
Normal file
@@ -0,0 +1,135 @@
|
||||
from pydantic import BaseModel, Field
|
||||
from typing import Optional, List, Dict, Any
|
||||
|
||||
|
||||
class FetchRawFileRequest(BaseModel):
|
||||
"""获取 Raw 文件请求"""
|
||||
|
||||
owner: str = Field(..., description="仓库所有者", example="MaiM-with-u")
|
||||
repo: str = Field(..., description="仓库名称", example="plugin-repo")
|
||||
branch: str = Field(..., description="分支名称", example="main")
|
||||
file_path: str = Field(..., description="文件路径", example="plugin_details.json")
|
||||
mirror_id: Optional[str] = Field(None, description="指定镜像源 ID")
|
||||
custom_url: Optional[str] = Field(None, description="自定义完整 URL")
|
||||
|
||||
|
||||
class FetchRawFileResponse(BaseModel):
|
||||
"""获取 Raw 文件响应"""
|
||||
|
||||
success: bool = Field(..., description="是否成功")
|
||||
data: Optional[str] = Field(None, description="文件内容")
|
||||
error: Optional[str] = Field(None, description="错误信息")
|
||||
mirror_used: Optional[str] = Field(None, description="使用的镜像源")
|
||||
attempts: int = Field(..., description="尝试次数")
|
||||
url: Optional[str] = Field(None, description="实际请求的 URL")
|
||||
|
||||
|
||||
class CloneRepositoryRequest(BaseModel):
|
||||
"""克隆仓库请求"""
|
||||
|
||||
owner: str = Field(..., description="仓库所有者", example="MaiM-with-u")
|
||||
repo: str = Field(..., description="仓库名称", example="plugin-repo")
|
||||
target_path: str = Field(..., description="目标路径(相对于插件目录)")
|
||||
branch: Optional[str] = Field(None, description="分支名称", example="main")
|
||||
mirror_id: Optional[str] = Field(None, description="指定镜像源 ID")
|
||||
custom_url: Optional[str] = Field(None, description="自定义克隆 URL")
|
||||
depth: Optional[int] = Field(None, description="克隆深度(浅克隆)", ge=1)
|
||||
|
||||
|
||||
class CloneRepositoryResponse(BaseModel):
|
||||
"""克隆仓库响应"""
|
||||
|
||||
success: bool = Field(..., description="是否成功")
|
||||
path: Optional[str] = Field(None, description="克隆路径")
|
||||
error: Optional[str] = Field(None, description="错误信息")
|
||||
mirror_used: Optional[str] = Field(None, description="使用的镜像源")
|
||||
attempts: int = Field(..., description="尝试次数")
|
||||
url: Optional[str] = Field(None, description="实际克隆的 URL")
|
||||
message: Optional[str] = Field(None, description="附加信息")
|
||||
|
||||
|
||||
class MirrorConfigResponse(BaseModel):
|
||||
"""镜像源配置响应"""
|
||||
|
||||
id: str = Field(..., description="镜像源 ID")
|
||||
name: str = Field(..., description="镜像源名称")
|
||||
raw_prefix: str = Field(..., description="Raw 文件前缀")
|
||||
clone_prefix: str = Field(..., description="克隆前缀")
|
||||
enabled: bool = Field(..., description="是否启用")
|
||||
priority: int = Field(..., description="优先级(数字越小优先级越高)")
|
||||
|
||||
|
||||
class AvailableMirrorsResponse(BaseModel):
|
||||
"""可用镜像源列表响应"""
|
||||
|
||||
mirrors: List[MirrorConfigResponse] = Field(..., description="镜像源列表")
|
||||
default_priority: List[str] = Field(..., description="默认优先级顺序(ID 列表)")
|
||||
|
||||
|
||||
class AddMirrorRequest(BaseModel):
|
||||
"""添加镜像源请求"""
|
||||
|
||||
id: str = Field(..., description="镜像源 ID", example="custom-mirror")
|
||||
name: str = Field(..., description="镜像源名称", example="自定义镜像源")
|
||||
raw_prefix: str = Field(..., description="Raw 文件前缀", example="https://example.com/raw")
|
||||
clone_prefix: str = Field(..., description="克隆前缀", example="https://example.com/clone")
|
||||
enabled: bool = Field(True, description="是否启用")
|
||||
priority: Optional[int] = Field(None, description="优先级")
|
||||
|
||||
|
||||
class UpdateMirrorRequest(BaseModel):
|
||||
"""更新镜像源请求"""
|
||||
|
||||
name: Optional[str] = Field(None, description="镜像源名称")
|
||||
raw_prefix: Optional[str] = Field(None, description="Raw 文件前缀")
|
||||
clone_prefix: Optional[str] = Field(None, description="克隆前缀")
|
||||
enabled: Optional[bool] = Field(None, description="是否启用")
|
||||
priority: Optional[int] = Field(None, description="优先级")
|
||||
|
||||
|
||||
class GitStatusResponse(BaseModel):
|
||||
"""Git 安装状态响应"""
|
||||
|
||||
installed: bool = Field(..., description="是否已安装 Git")
|
||||
version: Optional[str] = Field(None, description="Git 版本号")
|
||||
path: Optional[str] = Field(None, description="Git 可执行文件路径")
|
||||
error: Optional[str] = Field(None, description="错误信息")
|
||||
|
||||
|
||||
class InstallPluginRequest(BaseModel):
|
||||
"""安装插件请求"""
|
||||
|
||||
plugin_id: str = Field(..., description="插件 ID")
|
||||
repository_url: str = Field(..., description="插件仓库 URL")
|
||||
branch: Optional[str] = Field("main", description="分支名称")
|
||||
mirror_id: Optional[str] = Field(None, description="指定镜像源 ID")
|
||||
|
||||
|
||||
class VersionResponse(BaseModel):
|
||||
"""麦麦版本响应"""
|
||||
|
||||
version: str = Field(..., description="麦麦版本号")
|
||||
version_major: int = Field(..., description="主版本号")
|
||||
version_minor: int = Field(..., description="次版本号")
|
||||
version_patch: int = Field(..., description="补丁版本号")
|
||||
|
||||
|
||||
class UninstallPluginRequest(BaseModel):
|
||||
"""卸载插件请求"""
|
||||
|
||||
plugin_id: str = Field(..., description="插件 ID")
|
||||
|
||||
|
||||
class UpdatePluginRequest(BaseModel):
|
||||
"""更新插件请求"""
|
||||
|
||||
plugin_id: str = Field(..., description="插件 ID")
|
||||
repository_url: str = Field(..., description="插件仓库 URL")
|
||||
branch: Optional[str] = Field("main", description="分支名称")
|
||||
mirror_id: Optional[str] = Field(None, description="指定镜像源 ID")
|
||||
|
||||
|
||||
class UpdatePluginConfigRequest(BaseModel):
|
||||
"""更新插件配置请求"""
|
||||
|
||||
config: Dict[str, Any] = Field(..., description="配置数据")
|
||||
45
src/webui/schemas/statistics.py
Normal file
45
src/webui/schemas/statistics.py
Normal file
@@ -0,0 +1,45 @@
|
||||
from pydantic import BaseModel, Field
|
||||
from typing import Dict, Any, List
|
||||
|
||||
|
||||
class StatisticsSummary(BaseModel):
|
||||
"""统计数据摘要"""
|
||||
|
||||
total_requests: int = Field(0, description="总请求数")
|
||||
total_cost: float = Field(0.0, description="总花费")
|
||||
total_tokens: int = Field(0, description="总token数")
|
||||
online_time: float = Field(0.0, description="在线时间(秒)")
|
||||
total_messages: int = Field(0, description="总消息数")
|
||||
total_replies: int = Field(0, description="总回复数")
|
||||
avg_response_time: float = Field(0.0, description="平均响应时间")
|
||||
cost_per_hour: float = Field(0.0, description="每小时花费")
|
||||
tokens_per_hour: float = Field(0.0, description="每小时token数")
|
||||
|
||||
|
||||
class ModelStatistics(BaseModel):
|
||||
"""模型统计"""
|
||||
|
||||
model_name: str
|
||||
request_count: int
|
||||
total_cost: float
|
||||
total_tokens: int
|
||||
avg_response_time: float
|
||||
|
||||
|
||||
class TimeSeriesData(BaseModel):
|
||||
"""时间序列数据"""
|
||||
|
||||
timestamp: str
|
||||
requests: int = 0
|
||||
cost: float = 0.0
|
||||
tokens: int = 0
|
||||
|
||||
|
||||
class DashboardData(BaseModel):
|
||||
"""仪表盘数据"""
|
||||
|
||||
summary: StatisticsSummary
|
||||
model_stats: List[ModelStatistics]
|
||||
hourly_data: List[TimeSeriesData]
|
||||
daily_data: List[TimeSeriesData]
|
||||
recent_activity: List[Dict[str, Any]]
|
||||
Reference in New Issue
Block a user