补充插件依赖拓扑与缺失依赖风险视图

This commit is contained in:
liuwei
2026-04-30 17:35:48 +08:00
parent e3694b9320
commit 369b74e834
3 changed files with 266 additions and 0 deletions

View File

@@ -801,6 +801,85 @@ class PluginManager:
"execution_summary": execution_summary,
}
@staticmethod
def _normalize_snapshot_dependency_key(value: Any) -> str:
"""把依赖引用统一规整成可匹配的 key。"""
return str(value or "").strip().lower()
def _enrich_dependency_relationships(self, snapshots: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
"""为插件快照补齐依赖关系摘要。
设计目标:
1. 后台既要看“我依赖谁”,也要看“谁依赖我”;
2. 依赖声明有可能写插件名,也可能写模块名,因此这里做双 key 兼容;
3. 缺失依赖需要单独产出,便于页面上做风险聚合与高亮。
"""
normalized_snapshots = [dict(item or {}) for item in (snapshots or [])]
lookup_by_key: Dict[str, Dict[str, Any]] = {}
for snapshot in normalized_snapshots:
module_name = str(snapshot.get("module_name") or "").strip()
display_name = str(snapshot.get("name") or "").strip()
if module_name:
lookup_by_key[self._normalize_snapshot_dependency_key(module_name)] = snapshot
if display_name:
lookup_by_key[self._normalize_snapshot_dependency_key(display_name)] = snapshot
for snapshot in normalized_snapshots:
snapshot["resolved_dependencies"] = []
snapshot["missing_dependencies"] = []
snapshot["dependent_plugins"] = []
for snapshot in normalized_snapshots:
dependencies = list(snapshot.get("dependencies", []) or [])
resolved_dependencies = []
missing_dependencies = []
for dependency_name in dependencies:
normalized_key = self._normalize_snapshot_dependency_key(dependency_name)
target_snapshot = lookup_by_key.get(normalized_key)
if target_snapshot:
dependency_row = {
"name": str(target_snapshot.get("name") or "").strip(),
"module_name": str(target_snapshot.get("module_name") or "").strip(),
"status": str(target_snapshot.get("status") or "").strip(),
"status_label": str(target_snapshot.get("status_label") or "").strip(),
"governance_status": str(target_snapshot.get("governance_status") or "").strip(),
}
resolved_dependencies.append(dependency_row)
target_snapshot.setdefault("dependent_plugins", []).append(
{
"name": str(snapshot.get("name") or "").strip(),
"module_name": str(snapshot.get("module_name") or "").strip(),
"status": str(snapshot.get("status") or "").strip(),
"status_label": str(snapshot.get("status_label") or "").strip(),
"governance_status": str(snapshot.get("governance_status") or "").strip(),
}
)
else:
missing_dependencies.append(
{
"name": str(dependency_name or "").strip(),
}
)
snapshot["resolved_dependencies"] = resolved_dependencies
snapshot["missing_dependencies"] = missing_dependencies
snapshot["dependency_summary"] = {
"declared_count": len(dependencies),
"resolved_count": len(resolved_dependencies),
"missing_count": len(missing_dependencies),
"dependent_count": len(snapshot.get("dependent_plugins", []) or []),
"has_missing": len(missing_dependencies) > 0,
}
for snapshot in normalized_snapshots:
dependent_plugins = list(snapshot.get("dependent_plugins", []) or [])
dependent_plugins.sort(key=lambda item: (str(item.get("name") or ""), str(item.get("module_name") or "")))
snapshot["dependent_plugins"] = dependent_plugins
return normalized_snapshots
@staticmethod
def _status_to_label(status: str) -> str:
"""把运行态状态码转换成中文展示文案。"""
@@ -833,6 +912,8 @@ class PluginManager:
for module_name in sorted(discovered_module_names - loaded_module_names):
snapshots.append(self._build_unloaded_plugin_snapshot(module_name))
snapshots = self._enrich_dependency_relationships(snapshots)
snapshots.sort(
key=lambda item: (
0 if item.get("status") == "RUNNING" else 1,