Files
model_team_tools/core/plugin/plugins_card.py
T
feifei.xu 1b6796ec43 docs: 完善README文档与架构图,修复全量注释与日志问题
- README: 补充项目概述、技术栈、架构图(Mermaid)、插件生命周期时序图
- build.py: 补充模块和函数 docstring
- core/__init__.py: 修正模块说明(工具箱→插件系统)
- log.py: 修复过时注释,清理死代码,抑制第三方库日志刷屏
- plugin_registry.py: 修正矛盾注释,补充缺失日志,隐藏远程路径
- plugins.py: 修正过时注释,清理死代码和无用导入
- plugins_card.py: 修正错误类名注释,补充全量 docstring
- main.py: 修正错误注释,补充启动/退出/插件加载日志
2026-07-21 17:04:34 +08:00

109 lines
3.8 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 .plugin_registry import Event
from PySide6.QtWidgets import QFrame
from PySide6.QtCore import Signal
from .plugins_card_ui import Ui_FramePluginsCard
def parse_version(version: str) -> tuple:
"""将版本字符串解析为可比较的元组,如 '1.10.0' -> (1, 10, 0)。
非数字段保持原样(字符串与整数混排时按元组规则比较,足够覆盖
常见的 '1.0.0' / '1.10.3' 场景)。None/空值/解析失败返回 (0,)
视为最低版本。
"""
if not version:
return (0,)
try:
parts = []
for seg in str(version).split('.'):
seg = seg.strip()
if seg.isdigit():
parts.append(int(seg))
else:
parts.append(seg)
return tuple(parts) if parts else (0,)
except Exception:
return (0,)
class PluginsCard(QFrame, Ui_FramePluginsCard):
"""插件卡片组件。
继承自 QFrame 和 Ui_FramePluginsCardQt Designer 生成的 UI 界面),
负责展示单个插件的图标、名称、版本和描述,并提供安装/更新/卸载按钮。
Attributes:
name: 插件名称
info: 插件元数据字典,含 local version / remote version / description 等
"""
# 按钮点击信号,携带事件类型和插件名称
send_event_signal = Signal(Event, str)
def __init__(self, name: str, info: dict, parent=None) -> None:
"""初始化插件卡片。
Args:
name: 插件名称
info: 插件元数据字典
parent: 父组件,默认为 None
"""
super().__init__(parent)
self.setupUi(self)
self.name = name
self.info = info
self.initUI()
def initUI(self) -> None:
"""初始化卡片 UI:刷新显示内容并绑定按钮事件。"""
self.refresh()
self.textBrowser.setReadOnly(True)
self.pushButtonUpdate.clicked.connect(self.on_update_event)
self.pushButtonInstall.clicked.connect(self.on_install_event)
self.pushButtonUninstall.clicked.connect(self.on_uninstall_event)
def refresh(self) -> None:
"""根据 info 刷新卡片显示与按钮状态。"""
self.textBrowser.setMarkdown(self.to_card())
installed = self.info.get("local version") is not None
self.pushButtonInstall.setEnabled(not installed)
self.pushButtonUninstall.setEnabled(installed)
if installed:
remote = parse_version(self.info.get('remote version'))
local = parse_version(self.info.get('local version'))
self.pushButtonUpdate.setEnabled(remote > local)
else:
self.pushButtonUpdate.setEnabled(False)
def to_card(self) -> str:
"""将插件信息渲染为 Markdown 卡片文本。
Returns:
格式化的 Markdown 字符串,包含名称、版本和描述。
"""
remote_ver = self.info.get('remote version')
local_ver = self.info.get('local version')
desc = self.info.get('remote description') or self.info.get('local description') or '暂无'
card = f"# {self.name}\n\n"
card += f"**最新:** V{remote_ver}\n\n" if remote_ver else f"**最新:** 暂无版本信息\n\n"
if local_ver is None:
card += f"**当前:** 未安装!\n\n"
else:
card += f"**当前:** V{local_ver}\n\n"
card += f"**描述:** {desc}"
return card
def on_install_event(self) -> None:
"""触发安装事件。"""
self.send_event_signal.emit(Event.Install, self.name)
def on_uninstall_event(self) -> None:
"""触发卸载事件。"""
self.send_event_signal.emit(Event.Uninstall, self.name)
def on_update_event(self) -> None:
"""触发更新事件。"""
self.send_event_signal.emit(Event.Update, self.name)