mirror of
https://github.com/insistence/RuoYi-Vue3-FastAPI.git
synced 2026-10-06 09:41:55 +00:00
660 lines
27 KiB
Python
660 lines
27 KiB
Python
import asyncio
|
|
from dataclasses import dataclass
|
|
from typing import Any
|
|
|
|
from cli.tui.adapters.base import BaseDetailAdapter
|
|
from cli.tui.adapters.models import (
|
|
TUI_ADAPTER_MODEL_RENDERER,
|
|
DetailPageSnapshot,
|
|
DetailSectionSnapshot,
|
|
)
|
|
from cli.tui.copy import TUI_COPY
|
|
from cli.tui.diagnostics import TUI_DIAGNOSTIC_SERVICE
|
|
from cli.tui.queries import TUI_RUNTIME_QUERIES, TuiRuntimeQueryService
|
|
from cli.utils import SHELL_TEXT_FORMATTER
|
|
|
|
COMPLETION_PREVIEW_LINE_LIMIT = 12
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class AppDetailSourcePayloads:
|
|
"""
|
|
应用详情页原始数据源快照。
|
|
|
|
:param env_payload: `app env` 结果
|
|
:param config_payload: `app config` 结果
|
|
:param doctor_payload: `app doctor` 结果
|
|
:param routes_payload: `app routes` 结果
|
|
:param completion_payload: `completion doctor` 结果
|
|
:param completion_preview_result: `completion show` 命令结果
|
|
:param preview_shell: 当前补全脚本预览 shell
|
|
"""
|
|
|
|
env_payload: dict[str, Any] | None
|
|
config_payload: dict[str, Any] | None
|
|
doctor_payload: dict[str, Any] | None
|
|
routes_payload: dict[str, Any] | None
|
|
completion_payload: dict[str, Any] | None
|
|
completion_preview_result: Any
|
|
preview_shell: str
|
|
|
|
|
|
class AppDetailSnapshotCollector:
|
|
"""
|
|
应用详情页数据采集器。
|
|
|
|
该对象负责拉取应用详情页所需的多路 CLI 原始结果,
|
|
让 `AppDetailAdapter` 保持详情页编排职责。
|
|
|
|
:param section_builder: 应用详情分区构建器
|
|
"""
|
|
|
|
def __init__(
|
|
self,
|
|
section_builder: 'AppSectionBuilder',
|
|
query_service: TuiRuntimeQueryService | None = None,
|
|
) -> None:
|
|
"""
|
|
初始化应用详情页数据采集器。
|
|
|
|
:param section_builder: 应用详情分区构建器
|
|
:return: None
|
|
"""
|
|
self.section_builder = section_builder
|
|
self.query_service = query_service or TUI_RUNTIME_QUERIES
|
|
|
|
async def collect(self, env: str) -> AppDetailSourcePayloads:
|
|
"""
|
|
采集应用详情页所需原始结果。
|
|
|
|
:param env: 当前运行环境
|
|
:return: 应用详情页原始数据源快照
|
|
"""
|
|
env_payload, config_payload, doctor_payload, routes_payload, completion_payload = await asyncio.gather(
|
|
self.query_service.get_app_env(env),
|
|
self.query_service.get_app_config(env),
|
|
self.query_service.get_doctor(env),
|
|
self.query_service.get_app_routes(env),
|
|
self.query_service.get_completion_doctor(),
|
|
)
|
|
preview_shell = self.section_builder.resolve_completion_preview_shell(completion_payload)
|
|
completion_preview_result = await self.query_service.get_completion_preview(preview_shell)
|
|
return AppDetailSourcePayloads(
|
|
env_payload=env_payload,
|
|
config_payload=config_payload,
|
|
doctor_payload=doctor_payload,
|
|
routes_payload=routes_payload,
|
|
completion_payload=completion_payload,
|
|
completion_preview_result=completion_preview_result,
|
|
preview_shell=preview_shell,
|
|
)
|
|
|
|
|
|
class AppSectionBuilder:
|
|
"""
|
|
应用详情分区构建器。
|
|
|
|
该构建器负责将应用、补全和路由相关 CLI 结果转换为 TUI 详情页分区,
|
|
使详情页适配器本体只保留采集与编排职责。
|
|
"""
|
|
|
|
@staticmethod
|
|
def resolve_completion_preview_shell(payload: dict[str, Any] | None) -> str:
|
|
"""
|
|
解析补全脚本预览应使用的 shell。
|
|
|
|
:param payload: `completion doctor` JSON 负载
|
|
:return: shell 名称
|
|
"""
|
|
if not isinstance(payload, dict):
|
|
return 'bash'
|
|
active_shell = str(payload.get('activeShell') or '').strip().lower()
|
|
shells = payload.get('shells') if isinstance(payload.get('shells'), dict) else {}
|
|
if active_shell and isinstance(shells.get(active_shell), dict) and shells[active_shell].get('supported', False):
|
|
return active_shell
|
|
for shell_name in ('bash', 'zsh', 'fish', 'powershell'):
|
|
shell_payload = shells.get(shell_name)
|
|
if isinstance(shell_payload, dict) and shell_payload.get('supported', False):
|
|
return shell_name
|
|
return 'bash'
|
|
|
|
@staticmethod
|
|
def build_env_section(payload: dict[str, Any] | None) -> DetailSectionSnapshot:
|
|
"""
|
|
构建应用环境解析分区。
|
|
|
|
:param payload: `app env` JSON 负载
|
|
:return: 分区快照
|
|
"""
|
|
runtime = payload.get('runtime') if isinstance(payload, dict) else None
|
|
if not isinstance(runtime, dict):
|
|
return DetailSectionSnapshot(
|
|
title='环境解析',
|
|
status='fail',
|
|
lines=TUI_ADAPTER_MODEL_RENDERER.build_failure_lines(
|
|
payload, empty_label='环境信息', empty_value='不可用'
|
|
),
|
|
)
|
|
return DetailSectionSnapshot(
|
|
title='环境解析',
|
|
status='ok' if payload.get('ok', False) else 'fail',
|
|
lines=[
|
|
'## 环境映射',
|
|
f'CLI 目标环境: {runtime.get("cliEnv", "-")}',
|
|
f'配置模块环境: {runtime.get("configEnv", "-")}',
|
|
f'进程环境变量: {runtime.get("appEnv", "-") or "-"}',
|
|
'',
|
|
'## 文件与进程',
|
|
f'环境文件: {runtime.get("envFile", "-")}',
|
|
f'环境文件存在: {"是" if runtime.get("envFileExists", False) else "否"}',
|
|
f'后端目录: {SHELL_TEXT_FORMATTER.truncate_text(runtime.get("backendDir", "-"), 64)}',
|
|
f'Python 可执行文件: {SHELL_TEXT_FORMATTER.truncate_text(runtime.get("pythonExecutable", "-"), 64)}',
|
|
],
|
|
)
|
|
|
|
@staticmethod
|
|
def build_config_section(payload: dict[str, Any] | None) -> DetailSectionSnapshot:
|
|
"""
|
|
构建应用基础配置分区。
|
|
|
|
:param payload: `app config` JSON 负载
|
|
:return: 分区快照
|
|
"""
|
|
config = payload.get('config') if isinstance(payload, dict) else None
|
|
if not isinstance(config, dict):
|
|
return DetailSectionSnapshot(
|
|
title='应用配置',
|
|
status='fail',
|
|
lines=TUI_ADAPTER_MODEL_RENDERER.build_failure_lines(
|
|
payload, empty_label='应用配置', empty_value='不可用'
|
|
),
|
|
)
|
|
return DetailSectionSnapshot(
|
|
title='应用配置',
|
|
status='ok' if payload.get('ok', False) else 'fail',
|
|
lines=[
|
|
'## 应用入口',
|
|
f'应用名称: {SHELL_TEXT_FORMATTER.truncate_text(config.get("name", "-"), 40)}',
|
|
f'监听地址: {config.get("host", "-")}:{config.get("port", "-")}',
|
|
f'根路径: {config.get("rootPath", "-") or "/"}',
|
|
f'工作进程: {config.get("workers", "-")}',
|
|
f'热重载: {"开启" if config.get("reload", False) else "关闭"}',
|
|
'',
|
|
'## 文档与日志',
|
|
f'Swagger: {"关闭" if config.get("disableSwagger", False) else "开启"}',
|
|
f'ReDoc: {"关闭" if config.get("disableRedoc", False) else "开启"}',
|
|
f'日志级别: {config.get("logLevel", "-")}',
|
|
],
|
|
)
|
|
|
|
@staticmethod
|
|
def build_dependency_section(payload: dict[str, Any] | None) -> DetailSectionSnapshot:
|
|
"""
|
|
构建应用依赖配置分区。
|
|
|
|
:param payload: `app config` JSON 负载
|
|
:return: 分区快照
|
|
"""
|
|
config = payload.get('config') if isinstance(payload, dict) else None
|
|
if not isinstance(config, dict):
|
|
return DetailSectionSnapshot(
|
|
title='依赖配置',
|
|
status='fail',
|
|
lines=TUI_ADAPTER_MODEL_RENDERER.build_failure_lines(
|
|
payload, empty_label='依赖配置', empty_value='不可用'
|
|
),
|
|
)
|
|
return DetailSectionSnapshot(
|
|
title='依赖配置',
|
|
status='ok' if payload.get('ok', False) else 'fail',
|
|
lines=[
|
|
'## 数据库',
|
|
f'类型: {config.get("dbType", "-")}',
|
|
f'地址: {config.get("dbHost", "-")}:{config.get("dbPort", "-")}',
|
|
f'数据库名: {config.get("dbDatabase", "-")}',
|
|
'',
|
|
'## Redis 与加密',
|
|
f'Redis 地址: {config.get("redisHost", "-")}:{config.get("redisPort", "-")}',
|
|
f'传输加密: {"开启" if config.get("transportCryptoEnabled", False) else "关闭"}',
|
|
f'加密模式: {config.get("transportCryptoMode", "-")}',
|
|
],
|
|
)
|
|
|
|
def build_routes_section(self, payload: dict[str, Any] | None) -> DetailSectionSnapshot:
|
|
"""
|
|
构建应用路由摘要分区。
|
|
|
|
:param payload: `app routes` JSON 负载
|
|
:return: 分区快照
|
|
"""
|
|
if not isinstance(payload, dict) or not payload.get('ok', False):
|
|
return DetailSectionSnapshot(
|
|
title='路由摘要',
|
|
status='fail',
|
|
lines=TUI_ADAPTER_MODEL_RENDERER.build_failure_lines(payload, empty_label='路由', empty_value='不可用'),
|
|
)
|
|
|
|
count = payload.get('count', 0)
|
|
routes = payload.get('routes') if isinstance(payload.get('routes'), list) else []
|
|
grouped_routes = payload.get('groupedRoutes') if isinstance(payload.get('groupedRoutes'), dict) else {}
|
|
group_items = sorted(
|
|
((str(tag), len(items) if isinstance(items, list) else 0) for tag, items in grouped_routes.items()),
|
|
key=lambda item: (-item[1], item[0]),
|
|
)
|
|
|
|
lines = [
|
|
'## 路由规模',
|
|
f'总路由数: {count}',
|
|
f'标签分组数: {len(group_items)}',
|
|
'',
|
|
'## 主要标签',
|
|
]
|
|
if group_items:
|
|
lines.extend(f'> {tag} · {size} 条' for tag, size in group_items[:6])
|
|
else:
|
|
lines.append('> 暂无标签分组数据')
|
|
|
|
if routes:
|
|
lines.extend(['', '## 路由样本'])
|
|
for route in routes[:6]:
|
|
if not isinstance(route, dict):
|
|
continue
|
|
methods = '/'.join(route.get('methods', [])) if isinstance(route.get('methods'), list) else '-'
|
|
lines.extend(
|
|
[
|
|
f'> [{methods or "-"}] {SHELL_TEXT_FORMATTER.truncate_text(route.get("path", "-"), 48)}',
|
|
f'> {SHELL_TEXT_FORMATTER.truncate_text(route.get("summary", "-") or "-", 48)}',
|
|
]
|
|
)
|
|
else:
|
|
lines.extend(
|
|
[
|
|
'',
|
|
*TUI_ADAPTER_MODEL_RENDERER.build_empty_lines(
|
|
empty_label='路由样本',
|
|
empty_value='0 条',
|
|
detail='当前环境未返回可展示的路由样本',
|
|
suggestion=TUI_COPY.build_refresh_page_suggestion('应用', '确认当前环境是否已完成路由注册'),
|
|
),
|
|
]
|
|
)
|
|
|
|
return DetailSectionSnapshot(
|
|
title='路由摘要',
|
|
status='ok',
|
|
lines=lines,
|
|
)
|
|
|
|
@staticmethod
|
|
def build_completion_section(payload: dict[str, Any] | None) -> DetailSectionSnapshot:
|
|
"""
|
|
构建 shell completion 诊断分区。
|
|
|
|
:param payload: `completion doctor` JSON 负载
|
|
:return: 分区快照
|
|
"""
|
|
if not isinstance(payload, dict) or not payload.get('ok', False):
|
|
return DetailSectionSnapshot(
|
|
title='补全诊断',
|
|
status='fail',
|
|
lines=TUI_ADAPTER_MODEL_RENDERER.build_failure_lines(
|
|
payload, empty_label='补全诊断', empty_value='不可用'
|
|
),
|
|
)
|
|
|
|
shells = payload.get('shells') if isinstance(payload.get('shells'), dict) else {}
|
|
active_shell = str(payload.get('activeShell') or '-')
|
|
env_choices = payload.get('envChoices') if isinstance(payload.get('envChoices'), list) else []
|
|
active_shell_payload = shells.get(active_shell) if isinstance(shells.get(active_shell), dict) else None
|
|
target_file = active_shell_payload.get('targetFile', '-') if isinstance(active_shell_payload, dict) else '-'
|
|
source_command = (
|
|
active_shell_payload.get('sourceCommand', '-') if isinstance(active_shell_payload, dict) else '-'
|
|
)
|
|
install_command = (
|
|
active_shell_payload.get('recommendedInstallCommand', '-')
|
|
if isinstance(active_shell_payload, dict)
|
|
else payload.get('recommendedInstallCommand', '-')
|
|
)
|
|
|
|
lines = [
|
|
'## 当前环境',
|
|
f'活动 Shell: {active_shell}',
|
|
f'项目目录: {SHELL_TEXT_FORMATTER.truncate_text(payload.get("projectDir", "-"), 64)}',
|
|
f'补全环境变量: {payload.get("completeEnvVar", "-")}',
|
|
f'环境候选数: {len(env_choices)}',
|
|
'',
|
|
'## 激活建议',
|
|
f'目标脚本: {SHELL_TEXT_FORMATTER.truncate_text(target_file, 64)}',
|
|
f'加载命令: {SHELL_TEXT_FORMATTER.truncate_text(source_command, 72)}',
|
|
f'推荐安装命令: {SHELL_TEXT_FORMATTER.truncate_text(install_command, 72)}',
|
|
]
|
|
|
|
shell_lines = []
|
|
for shell_name in ('bash', 'zsh', 'fish', 'powershell'):
|
|
shell_payload = shells.get(shell_name)
|
|
if not isinstance(shell_payload, dict):
|
|
continue
|
|
supported = '支持' if shell_payload.get('supported', False) else '不支持'
|
|
detected = '当前 Shell' if shell_payload.get('detected', False) else '候选 Shell'
|
|
shell_lines.append(f'> {shell_name} · {supported} · {detected}')
|
|
if shell_lines:
|
|
lines.extend(['', '## Shell 支持'])
|
|
lines.extend(shell_lines)
|
|
|
|
return DetailSectionSnapshot(
|
|
title='补全诊断',
|
|
status='ok',
|
|
lines=lines,
|
|
)
|
|
|
|
def build_completion_preview_section(
|
|
self,
|
|
shell: str,
|
|
preview_result: Any,
|
|
) -> DetailSectionSnapshot:
|
|
"""
|
|
构建补全脚本预览分区。
|
|
|
|
:param shell: 当前预览 shell
|
|
:param preview_result: `completion show` 调用结果
|
|
:return: 分区快照
|
|
"""
|
|
stdout = str(getattr(preview_result, 'stdout', '') or '').strip()
|
|
stderr = str(getattr(preview_result, 'stderr', '') or '').strip()
|
|
returncode = int(getattr(preview_result, 'returncode', 1) or 0)
|
|
if returncode != 0:
|
|
return DetailSectionSnapshot(
|
|
title='补全脚本预览',
|
|
status='fail',
|
|
lines=TUI_ADAPTER_MODEL_RENDERER.build_failure_lines(
|
|
{'ok': False, 'message': stderr or stdout or '补全脚本生成失败'},
|
|
empty_label='补全脚本',
|
|
empty_value='不可用',
|
|
),
|
|
)
|
|
preview_lines = [
|
|
SHELL_TEXT_FORMATTER.truncate_text(line, 88) for line in stdout.splitlines()[:COMPLETION_PREVIEW_LINE_LIMIT]
|
|
]
|
|
if not preview_lines:
|
|
return DetailSectionSnapshot(
|
|
title='补全脚本预览',
|
|
status='info',
|
|
lines=TUI_ADAPTER_MODEL_RENDERER.build_empty_lines(
|
|
empty_label='补全脚本',
|
|
empty_value='0 行',
|
|
detail='当前 shell 的补全脚本未返回可预览内容',
|
|
suggestion=TUI_COPY.build_refresh_page_suggestion('应用', '重新生成补全脚本预览'),
|
|
),
|
|
)
|
|
return DetailSectionSnapshot(
|
|
title='补全脚本预览',
|
|
status='ok',
|
|
lines=[
|
|
'## 预览目标',
|
|
f'Shell: {shell}',
|
|
f'预览行数: {len(preview_lines)}',
|
|
'',
|
|
'## 脚本片段',
|
|
*preview_lines,
|
|
],
|
|
)
|
|
|
|
@staticmethod
|
|
def build_doctor_section(payload: dict[str, Any] | None) -> DetailSectionSnapshot:
|
|
"""
|
|
构建应用启动前检查分区。
|
|
|
|
:param payload: `app doctor` JSON 负载
|
|
:return: 分区快照
|
|
"""
|
|
if not isinstance(payload, dict):
|
|
return DetailSectionSnapshot(
|
|
title='启动前检查',
|
|
status='fail',
|
|
lines=TUI_ADAPTER_MODEL_RENDERER.build_failure_lines(
|
|
payload, empty_label='启动前检查', empty_value='不可用'
|
|
),
|
|
)
|
|
|
|
database = payload.get('database') if isinstance(payload.get('database'), dict) else {}
|
|
redis = payload.get('redis') if isinstance(payload.get('redis'), dict) else {}
|
|
crypto = payload.get('crypto') if isinstance(payload.get('crypto'), dict) else {}
|
|
return DetailSectionSnapshot(
|
|
title='启动前检查',
|
|
status='ok' if payload.get('ok', False) else 'fail',
|
|
lines=[
|
|
'## 检查结果',
|
|
f'环境: {payload.get("env", "-")}',
|
|
f'数据库: {"正常" if database.get("ok", False) else "异常"}',
|
|
f'> {SHELL_TEXT_FORMATTER.truncate_text(database.get("message", "-"), 64)}',
|
|
f'Redis: {"正常" if redis.get("ok", False) else "异常"}',
|
|
f'> {SHELL_TEXT_FORMATTER.truncate_text(redis.get("message", "-"), 64)}',
|
|
f'加密组件: {"正常" if crypto.get("ok", False) else "异常"}',
|
|
f'> {SHELL_TEXT_FORMATTER.truncate_text(crypto.get("message", "-"), 64)}',
|
|
],
|
|
)
|
|
|
|
@staticmethod
|
|
def build_run_entry_section() -> DetailSectionSnapshot:
|
|
"""
|
|
构建应用启动向导入口分区。
|
|
|
|
:return: 分区快照
|
|
"""
|
|
return DetailSectionSnapshot(
|
|
title='启动入口',
|
|
status='info',
|
|
lines=TUI_COPY.build_command_hint_lines(
|
|
scenario='准备启动当前环境应用时,可直接启动应用,或先通过向导确认目标环境与启动前检查选项。',
|
|
command=TUI_COPY.build_cli_command_hint('app', 'run', '--env=dev'),
|
|
guide='若需要先做启动前检查或切换环境,建议改用 `wizard app-run` 进入交互式启动流程。',
|
|
),
|
|
)
|
|
|
|
@staticmethod
|
|
def build_completion_install_entry_section() -> DetailSectionSnapshot:
|
|
"""
|
|
构建 shell 补全安装入口分区。
|
|
|
|
:return: 分区快照
|
|
"""
|
|
return DetailSectionSnapshot(
|
|
title='补全安装入口',
|
|
status='info',
|
|
lines=TUI_COPY.build_command_hint_lines(
|
|
scenario='准备为当前 Shell 安装或修复补全脚本时,可直接执行补全安装命令,并按需把激活命令写入 rc 文件。',
|
|
command=TUI_COPY.build_cli_command_hint('completion', 'install', '--activate', '--output=text'),
|
|
guide='当前页面提供补全诊断与安装入口;执行安装后可返回补全诊断分区确认 target file 和 source command 是否更新。',
|
|
),
|
|
)
|
|
|
|
@staticmethod
|
|
def build_overview_section(
|
|
env_payload: dict[str, Any] | None,
|
|
config_payload: dict[str, Any] | None,
|
|
doctor_payload: dict[str, Any] | None,
|
|
routes_payload: dict[str, Any] | None,
|
|
completion_payload: dict[str, Any] | None,
|
|
) -> DetailSectionSnapshot:
|
|
"""
|
|
构建应用页总览判断分区。
|
|
|
|
:param env_payload: `app env` JSON 负载
|
|
:param config_payload: `app config` JSON 负载
|
|
:param doctor_payload: `app doctor` JSON 负载
|
|
:param routes_payload: `app routes` JSON 负载
|
|
:param completion_payload: `completion doctor` JSON 负载
|
|
:return: 分区快照
|
|
"""
|
|
env_ok = bool(isinstance(env_payload, dict) and env_payload.get('ok', False))
|
|
config_ok = bool(isinstance(config_payload, dict) and config_payload.get('ok', False))
|
|
doctor_ok = bool(isinstance(doctor_payload, dict) and doctor_payload.get('ok', False))
|
|
routes_ok = bool(isinstance(routes_payload, dict) and routes_payload.get('ok', False))
|
|
completion_ok = bool(isinstance(completion_payload, dict) and completion_payload.get('ok', False))
|
|
route_count = routes_payload.get('count', 0) if isinstance(routes_payload, dict) else 0
|
|
runtime = (
|
|
env_payload.get('runtime')
|
|
if isinstance(env_payload, dict) and isinstance(env_payload.get('runtime'), dict)
|
|
else {}
|
|
)
|
|
config = (
|
|
config_payload.get('config')
|
|
if isinstance(config_payload, dict) and isinstance(config_payload.get('config'), dict)
|
|
else {}
|
|
)
|
|
|
|
status = 'ok'
|
|
conclusion = '应用基线正常,可继续查看环境映射、配置摘要与路由状态'
|
|
if not env_ok or not config_ok:
|
|
status = 'fail'
|
|
conclusion = '应用基础信息读取异常,优先确认环境映射与应用配置是否可用'
|
|
elif not doctor_ok:
|
|
status = 'fail'
|
|
conclusion = '启动前检查异常,优先确认数据库、Redis 和加密组件状态'
|
|
elif not completion_ok:
|
|
status = 'warn'
|
|
conclusion = '补全诊断读取异常,建议优先确认项目目录、Shell 类型和补全脚本状态'
|
|
elif not routes_ok:
|
|
status = 'warn'
|
|
conclusion = '路由摘要读取异常,建议先确认当前环境是否完成应用初始化'
|
|
elif int(route_count or 0) <= 0:
|
|
status = 'info'
|
|
conclusion = '当前未返回注册路由,建议检查路由注册流程与运行上下文'
|
|
|
|
return DetailSectionSnapshot(
|
|
title='总览判断',
|
|
status=status,
|
|
lines=[
|
|
'## 当前结论',
|
|
conclusion,
|
|
'',
|
|
'## 核心指标',
|
|
f'CLI 环境: {runtime.get("cliEnv", "-")}',
|
|
f'配置环境: {runtime.get("configEnv", "-")}',
|
|
f'监听地址: {config.get("host", "-")}:{config.get("port", "-")}',
|
|
f'注册路由: {route_count} 条',
|
|
f'启动前检查: {"正常" if doctor_ok else "异常"}',
|
|
f'传输加密: {"开启" if config.get("transportCryptoEnabled", False) else "关闭"}',
|
|
f'补全诊断: {"正常" if completion_ok else "异常"}',
|
|
'',
|
|
'## 建议入口',
|
|
'优先关注:环境解析 / 应用配置 / 启动前检查 / 补全诊断 / 路由摘要 / 启动入口',
|
|
],
|
|
)
|
|
|
|
def build_sections(
|
|
self,
|
|
*,
|
|
env_payload: dict[str, Any] | None,
|
|
config_payload: dict[str, Any] | None,
|
|
doctor_payload: dict[str, Any] | None,
|
|
routes_payload: dict[str, Any] | None,
|
|
completion_payload: dict[str, Any] | None,
|
|
completion_preview_result: Any,
|
|
preview_shell: str,
|
|
) -> list[DetailSectionSnapshot]:
|
|
"""
|
|
构建应用页全部详情分区。
|
|
|
|
:param env_payload: `app env` 结果负载
|
|
:param config_payload: `app config` 结果负载
|
|
:param doctor_payload: `app doctor` 结果负载
|
|
:param routes_payload: `app routes` 结果负载
|
|
:param completion_payload: `completion doctor` 结果负载
|
|
:param completion_preview_result: `completion show` 命令结果
|
|
:param preview_shell: 当前预览 shell
|
|
:return: 详情分区列表
|
|
"""
|
|
return [
|
|
self.build_overview_section(
|
|
env_payload,
|
|
config_payload,
|
|
doctor_payload,
|
|
routes_payload,
|
|
completion_payload,
|
|
),
|
|
self.build_env_section(env_payload),
|
|
self.build_config_section(config_payload),
|
|
self.build_dependency_section(config_payload),
|
|
self.build_doctor_section(doctor_payload),
|
|
self.build_completion_section(completion_payload),
|
|
self.build_completion_preview_section(preview_shell, completion_preview_result),
|
|
self.build_completion_install_entry_section(),
|
|
self.build_routes_section(routes_payload),
|
|
self.build_run_entry_section(),
|
|
]
|
|
|
|
|
|
class AppDetailAdapter(BaseDetailAdapter):
|
|
"""
|
|
应用详情页适配器。
|
|
|
|
该适配器负责采集应用相关 CLI 结果,并委托分区构建器组装为
|
|
TUI 详情页快照。
|
|
"""
|
|
|
|
def __init__(
|
|
self,
|
|
section_builder: AppSectionBuilder | None = None,
|
|
snapshot_collector: AppDetailSnapshotCollector | None = None,
|
|
) -> None:
|
|
"""
|
|
初始化应用详情页适配器。
|
|
|
|
:param section_builder: 应用详情分区构建器
|
|
:param snapshot_collector: 应用详情页数据采集器
|
|
:return: None
|
|
"""
|
|
super().__init__(
|
|
page_title='应用',
|
|
search_view_key='app',
|
|
default_suggestions=[
|
|
'总览判断',
|
|
'环境解析',
|
|
'应用配置',
|
|
'依赖配置',
|
|
'启动前检查',
|
|
'补全诊断',
|
|
'补全脚本预览',
|
|
'补全安装入口',
|
|
'路由摘要',
|
|
'启动入口',
|
|
],
|
|
)
|
|
self.section_builder = section_builder or AppSectionBuilder()
|
|
self.snapshot_collector = snapshot_collector or AppDetailSnapshotCollector(self.section_builder)
|
|
|
|
async def collect_snapshot(self, env: str, query: str = '') -> DetailPageSnapshot:
|
|
"""
|
|
采集应用状态页只读快照。
|
|
|
|
:param env: 当前运行环境
|
|
:param query: 当前搜索词
|
|
:return: 页面快照
|
|
"""
|
|
source_payloads = await self.snapshot_collector.collect(env)
|
|
sections = self.section_builder.build_sections(
|
|
env_payload=source_payloads.env_payload,
|
|
config_payload=source_payloads.config_payload,
|
|
doctor_payload=source_payloads.doctor_payload,
|
|
routes_payload=source_payloads.routes_payload,
|
|
completion_payload=source_payloads.completion_payload,
|
|
completion_preview_result=source_payloads.completion_preview_result,
|
|
preview_shell=source_payloads.preview_shell,
|
|
)
|
|
return DetailPageSnapshot(
|
|
title='应用',
|
|
subtitle=TUI_DIAGNOSTIC_SERVICE.build_app_diagnostic_subtitle(
|
|
source_payloads.env_payload,
|
|
source_payloads.config_payload,
|
|
source_payloads.doctor_payload,
|
|
source_payloads.routes_payload,
|
|
source_payloads.completion_payload,
|
|
),
|
|
sections=self.filter_sections(sections, query),
|
|
search=self.resolve_search_context(query),
|
|
)
|
|
|
|
|
|
APP_DETAIL_ADAPTER = AppDetailAdapter()
|