Files
MoviePilot/app/schemas/plugin.py
jxxghp 4de4fa4391 fix: 插件文件夹响应模型兼容新版对象格式
GET /plugin/folders 的响应模型 PluginFoldersData 只能校验旧版
数组格式,前端实际保存的是含展示配置的对象格式,导致建文件夹/
移入插件后刷新时响应校验失败(500),文件夹恢复为空。改为同时
兼容新旧两种格式。
2026-08-13 22:06:22 +08:00

197 lines
6.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from typing import Optional, List, Dict, Union
from pydantic import BaseModel, Field, RootModel
from app.schemas.common import JsonData
class Plugin(BaseModel):
"""
插件信息
"""
id: str = None
# 插件名称
plugin_name: Optional[str] = None
# 插件描述
plugin_desc: Optional[str] = None
# 插件图标
plugin_icon: Optional[str] = None
# 插件版本
plugin_version: Optional[str] = None
# 插件标签
plugin_label: Optional[str] = None
# 插件作者
plugin_author: Optional[str] = None
# 作者主页
author_url: Optional[str] = None
# 插件配置项ID前缀
plugin_config_prefix: Optional[str] = None
# 加载顺序
plugin_order: Optional[int] = 0
# 可使用的用户级别
auth_level: Optional[int] = 0
# 是否已安装
installed: Optional[bool] = False
# 运行状态
state: Optional[bool] = False
# 是否有详情页面
has_page: Optional[bool] = False
# 是否有新版本
has_update: Optional[bool] = False
# 主系统版本是否兼容
system_version_compatible: Optional[bool] = True
# 主系统版本兼容提示
system_version_message: Optional[str] = None
# 主系统版本限定范围
system_version: Optional[str] = None
# 是否声明支持通过 GitHub Release 资产安装
release: Optional[bool] = False
# 是否本地
is_local: Optional[bool] = False
# 仓库地址
repo_url: Optional[str] = None
# 安装次数
install_count: Optional[int] = 0
# 更新记录
history: Optional[dict[str, str]] = Field(default_factory=dict)
# 添加时间,值越小表示越靠后发布
add_time: Optional[int] = 0
# 插件公钥
plugin_public_key: Optional[str] = None
class PluginDashboard(Plugin):
"""
插件仪表盘
"""
id: Optional[str] = None
# 名称
name: Optional[str] = None
# 仪表板key
key: Optional[str] = None
# 演染模式
render_mode: Optional[str] = Field(default="vuetify")
# 全局配置
attrs: Optional[dict[str, JsonData]] = Field(default_factory=dict)
# col列数
cols: Optional[dict[str, JsonData]] = Field(default_factory=dict)
# 页面元素
elements: Optional[List[dict[str, JsonData]]] = Field(default_factory=list)
class PluginSidebarNavItem(BaseModel):
"""
插件侧栏导航项(前端全页路由)
"""
plugin_id: str = Field(description="插件 ID")
nav_key: str = Field(description="导航键,对应 URL 段")
title: str = Field(description="侧栏标题")
icon: str = Field(default="mdi-puzzle", description="MDI 图标名")
section: str = Field(
description="分组start / discovery / subscribe / organize / system",
)
permission: Optional[str] = Field(
default=None,
description="权限subscribe / discovery / search / manage / admin",
)
order: int = Field(default=0, description="同组内排序,越小越靠前")
class PluginRatingRequest(BaseModel):
"""插件评分请求"""
rating: float = Field(
ge=0.1,
le=5.0,
multiple_of=0.1,
description="评分,范围 0.1 至 5.0,精确到 0.1",
)
class PluginRating(BaseModel):
"""插件评分结果"""
plugin_id: str = Field(description="插件 ID")
average_rating: float = Field(default=0.0, description="平均评分")
rating_count: int = Field(default=0, description="评分人数")
user_rating: Optional[float] = Field(default=None, description="当前安装实例评分")
class PluginRatingMap(RootModel[Dict[str, PluginRating]]):
"""插件 ID 与评分结果的映射。"""
class PluginMemoryInfo(BaseModel):
"""插件内存信息"""
plugin_id: str = Field(description="插件ID")
plugin_name: str = Field(description="插件名称")
plugin_version: str = Field(description="插件版本")
total_memory_bytes: int = Field(description="总内存使用量(字节)")
total_memory_mb: float = Field(description="总内存使用量(MB)")
object_count: int = Field(description="对象数量")
calculation_time_ms: float = Field(description="计算耗时(毫秒)")
timestamp: float = Field(description="统计时间戳")
error: Optional[str] = Field(default=None, description="错误信息")
object_details: Optional[List[Dict[str, JsonData]]] = Field(default=None, description="大对象详情")
class PluginRemoteInfo(BaseModel):
"""插件模块联邦远程入口。"""
id: str
url: str
name: str
class PluginReleaseItem(BaseModel):
"""可安装的插件 Release 版本。"""
version: str
tag_name: str
name: str
published_at: Optional[str] = None
body: str = ""
asset_name: str
is_latest: bool = False
is_current: bool = False
class PluginReleaseData(BaseModel):
"""插件 Release 能力与版本列表。"""
release_supported: bool = False
latest_version: Optional[str] = None
current_version: Optional[str] = None
items: List[PluginReleaseItem] = Field(default_factory=list)
class PluginFolderConfigData(BaseModel):
"""新版插件文件夹配置(对象格式,含展示配置与插件列表)。"""
# 文件夹内插件 ID 列表
plugins: List[str] = Field(default_factory=list)
# 文件夹排序值
order: Optional[int] = None
# 文件夹图标
icon: Optional[str] = None
# 文件夹颜色
color: Optional[str] = None
# 文件夹渐变
gradient: Optional[str] = None
# 文件夹背景
background: Optional[str] = None
# 是否显示图标(前端字段为驼峰命名)
show_icon: Optional[bool] = Field(default=None, alias="showIcon")
class PluginFoldersData(RootModel[Dict[str, Union[List[str], PluginFolderConfigData]]]):
"""插件文件夹与插件配置映射,兼容旧版数组格式与新版对象格式。"""
class PluginDashboardMetaItem(BaseModel):
"""插件仪表板入口摘要。"""
id: str
name: Optional[str] = None
key: Optional[str] = None