调整部分前端布局和后端增删改逻辑

This commit is contained in:
焦龙言
2026-09-20 10:38:10 +08:00
parent acddc8a237
commit 3edba99d2d
227 changed files with 122871 additions and 839 deletions
@@ -0,0 +1,23 @@
from cli.tui.copy.actions import TuiActionCopyMixin
from cli.tui.copy.navigation import TuiNavigationCopyMixin
from cli.tui.copy.workspace import TuiWorkspaceCopyMixin
class TuiCopyService(TuiNavigationCopyMixin, TuiActionCopyMixin, TuiWorkspaceCopyMixin):
"""
TUI 文案构造服务。
该服务通过组合导航、动作和工作区文案混入对象,统一对外提供
TUI 所需的文案构造能力,避免入口模块继续堆积实现细节。
"""
TUI_COPY = TuiCopyService()
__all__ = [
'TUI_COPY',
'TuiActionCopyMixin',
'TuiCopyService',
'TuiNavigationCopyMixin',
'TuiWorkspaceCopyMixin',
]
@@ -0,0 +1,298 @@
from cli.tui.copy.fragments import (
ACTION_CONSEQUENCE_TEXTS,
ACTION_FEEDBACK_COPY,
ACTION_HINT_COPY,
ACTION_LABELS,
ACTION_NOTIFICATION_COPY,
ACTION_PREVIEW_FIELD_LABELS,
ACTION_PREVIEW_TITLES,
ACTION_PURPOSE_LABELS,
ACTION_RESULT_FIELD_LABELS,
ACTION_SCOPE_LABELS,
CAPABILITY_HINT_LABELS,
CAPABILITY_LABELS,
COMMAND_HINT_TITLES,
GENERAL_COPY,
)
from cli.utils import NESTED_CLI_SUPPORT, SHELL_TEXT_FORMATTER
class TuiActionCopyMixin:
"""
TUI 动作与能力文案混入。
"""
@staticmethod
def build_action_confirm_hint() -> str:
"""
构建动作确认弹窗底部提示文案。
:return: 确认提示文案
"""
return GENERAL_COPY['action_confirm_hint']
@staticmethod
def build_action_confirm_cancel_label() -> str:
"""
构建动作确认弹窗取消按钮文案。
:return: 取消按钮文案
"""
return GENERAL_COPY['action_confirm_cancel_label']
@staticmethod
def build_action_label(action_key: str) -> str:
"""
根据动作标识构建动作标题文案。
:param action_key: 动作标识
:return: 动作标题文案
"""
normalized_key = str(action_key).strip().lower()
return ACTION_LABELS.get(normalized_key, normalized_key)
@staticmethod
def build_action_scope_label(action_key: str) -> str:
"""
根据动作标识构建作用范围文案。
:param action_key: 动作标识
:return: 作用范围文案
"""
normalized_key = str(action_key).strip().lower()
return ACTION_SCOPE_LABELS.get(normalized_key, normalized_key)
@staticmethod
def build_action_purpose_label(action_key: str) -> str:
"""
根据动作标识构建用途文案。
:param action_key: 动作标识
:return: 用途文案
"""
normalized_key = str(action_key).strip().lower()
return ACTION_PURPOSE_LABELS.get(normalized_key, normalized_key)
@staticmethod
def build_action_preview_title(title_key: str) -> str:
"""
根据预览区块标识构建标题文案。
:param title_key: 预览区块标识
:return: 标题文案
"""
normalized_key = str(title_key).strip().lower()
return ACTION_PREVIEW_TITLES.get(normalized_key, normalized_key)
@staticmethod
def build_action_preview_field_label(field_key: str) -> str:
"""
根据预览字段标识构建字段文案。
:param field_key: 预览字段标识
:return: 字段文案
"""
normalized_key = str(field_key).strip().lower()
return ACTION_PREVIEW_FIELD_LABELS.get(normalized_key, normalized_key)
@staticmethod
def build_action_result_field_label(field_key: str) -> str:
"""
根据结果字段标识构建字段文案。
:param field_key: 结果字段标识
:return: 字段文案
"""
normalized_key = str(field_key).strip().lower()
return ACTION_RESULT_FIELD_LABELS.get(normalized_key, normalized_key)
@staticmethod
def build_action_notification_title() -> str:
"""
构建动作通知标题文案。
:return: 通知标题文案
"""
return ACTION_NOTIFICATION_COPY['title']
@staticmethod
def build_action_unavailable_message() -> str:
"""
构建无可执行动作时的提示文案。
:return: 提示文案
"""
return ACTION_NOTIFICATION_COPY['unavailable_message']
@staticmethod
def build_action_empty_line() -> str:
"""
构建无可执行动作时的空态占位文案。
:return: 空态占位文案
"""
return ACTION_NOTIFICATION_COPY['empty_line']
@staticmethod
def build_action_consequence_text(consequence_key: str) -> str:
"""
根据后果说明标识构建说明文案。
:param consequence_key: 后果说明标识
:return: 后果说明文案
"""
normalized_key = str(consequence_key).strip().lower()
return ACTION_CONSEQUENCE_TEXTS.get(normalized_key, normalized_key)
@staticmethod
def build_capability_label(capability_key: str) -> str:
"""
根据能力标识构建展示标签文案。
:param capability_key: 能力标识
:return: 展示标签文案
"""
normalized_key = str(capability_key).strip().lower()
return CAPABILITY_LABELS.get(normalized_key, normalized_key)
@staticmethod
def build_capability_hint_label(capability_key: str) -> str:
"""
根据能力标识构建顶部提示短标签文案。
:param capability_key: 能力标识
:return: 短标签文案
"""
normalized_key = str(capability_key).strip().lower()
return CAPABILITY_HINT_LABELS.get(normalized_key, normalized_key)
@staticmethod
def build_action_running_message(label: str) -> str:
"""
构建动作执行中的提示文案。
:param label: 动作标题
:return: 提示文案
"""
return f'正在执行:{label}'
@staticmethod
def build_browser_action_hint_text(view_key: str, interaction_hint: str) -> str:
"""
构建浏览页动作提示文本。
:param view_key: 当前页面视图标识
:param interaction_hint: 通用浏览提示
:return: 动作提示文本
"""
normalized_view = str(view_key).strip().lower()
template = ACTION_HINT_COPY['browser_templates'].get(normalized_view, ACTION_HINT_COPY['browser_default'])
return template.format(interaction_hint=interaction_hint)
@staticmethod
def build_detail_action_hint_text(view_key: str, interaction_hint: str) -> str:
"""
构建详情页动作提示文本。
:param view_key: 当前页面视图标识
:param interaction_hint: 通用浏览提示
:return: 动作提示文本
"""
normalized_view = str(view_key).strip().lower()
template = ACTION_HINT_COPY['detail_templates'].get(normalized_view, ACTION_HINT_COPY['detail_default'])
return template.format(interaction_hint=interaction_hint)
@staticmethod
def build_action_line(key: str, label: str) -> str:
"""
构建单条动作快捷键信息。
:param key: 快捷键
:param label: 动作标题
:return: 文本文案
"""
return f'动作键 [{key}] · {label}'
@staticmethod
def build_capability_hint_text(capability_labels: list[str], interaction_hint: str, *, fallback: str) -> str:
"""
根据能力标签列表构建统一动作提示文本。
:param capability_labels: 动作标签列表
:param interaction_hint: 通用浏览提示
:param fallback: 缺省提示模板
:return: 动作提示文本
"""
if not capability_labels:
return fallback.format(interaction_hint=interaction_hint)
return f'动作键:{" ".join(capability_labels)} | {interaction_hint}'
@staticmethod
def build_action_result_message_line(label: str, value: str) -> str:
"""
构建动作结果详情的单行文案。
:param label: 字段标题
:param value: 字段值
:return: 文本文案
"""
return f'{label}: {value}'
@staticmethod
def build_cli_command_hint(*command_args: str) -> str:
"""
构建 TUI 中展示的 CLI 命令提示文本。
:param command_args: CLI 命令参数
:return: 可直接复制执行的命令文本
"""
return SHELL_TEXT_FORMATTER.format_shell_command(NESTED_CLI_SUPPORT.build_nested_cli_command(*command_args))
@staticmethod
def build_command_hint_lines(
*,
scenario: str,
command: str,
guide: str,
) -> list[str]:
"""
构建统一的命令入口提示文本。
:param scenario: 适用场景说明
:param command: 推荐命令
:param guide: 使用说明
:return: 文本行列表
"""
return [
COMMAND_HINT_TITLES['scenario'],
scenario,
'',
COMMAND_HINT_TITLES['command'],
command,
'',
COMMAND_HINT_TITLES['guide'],
guide,
]
@staticmethod
def build_labeled_value_line(label: str, value: str) -> str:
"""
构建通用的“标签: 值”文案。
:param label: 字段标题
:param value: 字段值
:return: 文本文案
"""
return f'{label}: {value}'
@staticmethod
def build_action_result_toast(label: str, outcome: str, message: str) -> str:
"""
构建动作完成后的通知文案。
:param label: 动作标题
:param outcome: 执行结果
:param message: 结果摘要
:return: 通知文案
"""
return f'{ACTION_FEEDBACK_COPY["toast_prefix"]} · {label} · {outcome} · {message}'
@@ -0,0 +1,339 @@
VIEW_LABELS = {
'dashboard': '总览',
'app': '应用',
'ops': '运维',
'database': '数据库',
'cache': '缓存',
'jobs': '任务',
'gen': '代码生成',
'configs': '参数配置',
'crypto': '加密',
}
STATUS_LABELS = {
'ok': '正常',
'success': '正常',
'healthy': '正常',
'fail': '失败',
'error': '失败',
'down': '失败',
'warn': '警告',
'warning': '警告',
'degraded': '警告',
'info': '信息',
}
GENERAL_COPY = {
'action_confirm_cancel_label': '取消',
'action_confirm_hint': '按键提示 · [Enter] 确认执行 [Esc] 取消返回',
'more_detail_hint': '> 进入对应页面查看更多',
'tui_command_help': '进入只读巡检工作台',
'tui_missing_dependency_hint': '请重新执行 `pip install -r requirements.txt` 或 `pip install -r requirements-pg.txt`',
'tui_missing_dependency_message': '当前环境未安装 TUI 可选依赖,无法启动 `shierfeng tui`',
}
STATE_SUGGESTIONS = {
'dashboard_empty': '按 [R] 刷新,或进入对应页面查看更多上下文',
'dashboard_failure': '按 [R] 刷新,或进入对应页面查看完整诊断信息',
'empty': '可按 [R] 刷新,或切换到其他页面继续查看',
'failure': '可按 [R] 刷新,或切换页面后重新进入',
'loading': '可继续切换其他区域,当前内容加载完成后会自动刷新',
}
PAGE_SUBTITLES = {
'crypto': '查看运行校验、公钥身份和兼容版本信息',
'ops': '查看基础连通性、依赖版本与服务器资源',
}
NAVIGATION_DESCRIPTIONS = {
'dashboard': '全链路态势与关键健康信号',
'app': '环境解析、配置快照、补全诊断与路由摘要',
'ops': '健康检查、依赖版本与服务器资源',
'database': '连接、迁移版本与存储状态',
'cache': 'Redis 容量、热点与命中信号',
'jobs': '定时任务、执行轨迹与失败样本',
'gen': '业务表、字段与生成配置',
'configs': '配置巡检、漂移与异常值',
'crypto': '传输加密校验、公钥身份与兼容版本',
}
DASHBOARD_HERO_COPY = {
'subtitle': '先看整体风险和巡检结论,再进入数据库、缓存、任务等分区继续定位',
'title': '运行驾驶舱',
}
STATUS_PANEL_COPY = {
'empty': '暂无数据',
}
ACTION_LABELS = {
'app_run': '直接启动应用',
'app_run_wizard': '打开启动向导',
'cache_clear_wizard': '打开缓存清理向导',
'cache_warmup': '执行缓存预热',
'completion_install': '安装当前 Shell 补全',
'config_sync': '刷新参数缓存',
'crypto_keygen': '打开密钥生成入口',
'crypto_rotate_dry_run': '执行轮换预演',
'db_init_dry_run': '执行初始化预演',
'db_upgrade_wizard': '打开升级向导',
'gen_export_dry_run': '执行导出预演',
'gen_export_wizard': '打开导出向导',
'gen_import_wizard': '打开导入向导',
'gen_sync_db': '同步数据库表结构',
'job_pause': '暂停任务',
'job_resume': '恢复任务',
'job_run_once': '执行一次任务',
'job_sync': '同步调度配置',
'ops_ping_db': '执行数据库探活',
'ops_ping_redis': '执行 Redis 探活',
'prod_check_wizard': '打开生产巡检向导',
}
ACTION_SCOPE_LABELS = {
'cache_warmup': '系统字典与系统参数基础缓存',
'completion_install': '当前终端活动 Shell 的补全安装流程',
'config_sync': '当前环境全部系统参数',
'db_init_dry_run': '当前环境数据库初始化流程',
'gen_export_dry_run': '当前业务表的代码导出结果预演',
'gen_sync_db': '当前业务表对应的生成配置和物理表结构',
'job_sync': '当前环境调度器配置',
'ops_ping_db': '当前环境数据库连接与基础读写探活',
'ops_ping_redis': '当前环境 Redis 连接与基础命令探活',
}
ACTION_PURPOSE_LABELS = {
'cache_warmup': '重建运行所需的基础缓存内容',
'completion_install': '自动识别当前 Shell,写入补全脚本并按需更新 rc 文件激活命令',
'config_sync': '将数据库中的参数值重新写入 Redis 缓存',
'db_init_dry_run': '仅预演初始化到最新迁移版本,不直接执行真实升级',
'gen_export_dry_run': '先演练导出流程并确认输出模式、模板数量和结果摘要',
'gen_sync_db': '将数据库中的最新字段结构同步回当前业务表配置',
'job_sync': '将最新任务配置同步到调度执行器',
'ops_ping_db': '快速确认当前环境数据库是否可连接并返回基础探活结果',
'ops_ping_redis': '快速确认当前环境 Redis 是否可连接并返回基础命令探活结果',
}
ACTION_PREVIEW_TITLES = {
'command': '## 执行命令',
'consequence': '## 确认后果',
'env': '## 执行环境',
'summary': '## 动作信息',
}
ACTION_PREVIEW_FIELD_LABELS = {
'current_status': '当前状态',
'job': '任务',
'job_id': '任务 ID',
'purpose': '用途',
'scope': '作用范围',
'target_action': '目标动作',
'target_env': '目标环境',
}
ACTION_RESULT_FIELD_LABELS = {
'count': '影响数量',
'exit_code': '退出码',
'fail': '失败',
'hint': '建议',
'job_id': '任务 ID',
'name': '动作名称',
'operation': '操作标签',
'outcome': '结果',
'service': '服务反馈',
'success': '成功',
'summary': '摘要',
}
ACTION_CONSEQUENCE_TEXTS = {
'external': '确认后会暂时挂起 TUI,并在当前终端中执行对应命令;命令结束后自动返回工作台。',
'preview': '确认后会立即执行对应 CLI 低风险命令,并按结果刷新当前页面。',
'wizard': '确认后会暂时挂起 TUI,并在当前终端中打开对应向导;向导结束后自动返回工作台。',
}
APP_BINDING_LABELS = {
'next': '下一页',
'previous': '上一页',
'quit': '退出',
'refresh': '刷新',
'sidebar': '侧边栏',
}
INTERNAL_BINDING_LABELS = {
'action_global': '同步动作',
'action_primary': '执行动作',
'action_secondary': '切换状态',
'action_utility': '工具动作',
'clear_search': '清空搜索',
'confirm_cancel': '取消',
'confirm_submit': '确认',
'end': '跳到末尾',
'filter_1': '筛选项 1',
'filter_2': '筛选项 2',
'filter_3': '筛选项 3',
'filter_4': '筛选项 4',
'focus_left': '向左聚焦',
'focus_right': '向右聚焦',
'home': '回到顶部',
'page_down': '下翻页',
'page_up': '上翻页',
'scroll_down': '向下滚动',
'scroll_up': '向上滚动',
'search': '页内搜索',
}
BROWSER_EMPTY_RECORD_COPY = {
'detail': '当前页面没有可浏览记录',
'label': '记录列表',
'summary': '当前页面没有可浏览记录',
'title': '暂无记录数据',
'value': '暂无数据',
}
BROWSER_LOADING_COPY = {
'detail': '正在后台加载当前记录详情,请稍候',
'label': '详情状态',
'title': '详情加载中',
'value': '加载中',
}
DETAIL_EMPTY_SECTION_COPY = {
'detail_page': '当前页面没有可展示的分区详情',
'detail_record': '当前记录没有可展示的分区详情',
'label': '分区详情',
'title': '暂无分区数据',
'value': '暂无内容',
}
CAPABILITY_LABELS = {
'app_run': ACTION_LABELS['app_run'],
'app_run_wizard': ACTION_LABELS['app_run_wizard'],
'cache_clear_wizard': ACTION_LABELS['cache_clear_wizard'],
'cache_warmup': ACTION_LABELS['cache_warmup'],
'completion_install': ACTION_LABELS['completion_install'],
'config_sync': ACTION_LABELS['config_sync'],
'crypto_keygen': ACTION_LABELS['crypto_keygen'],
'crypto_rotate_dry_run': ACTION_LABELS['crypto_rotate_dry_run'],
'db_init_dry_run': ACTION_LABELS['db_init_dry_run'],
'db_upgrade_wizard': ACTION_LABELS['db_upgrade_wizard'],
'gen_export_dry_run': ACTION_LABELS['gen_export_dry_run'],
'gen_export_wizard': ACTION_LABELS['gen_export_wizard'],
'gen_import_wizard': ACTION_LABELS['gen_import_wizard'],
'gen_sync_db': ACTION_LABELS['gen_sync_db'],
'job_run_once': ACTION_LABELS['job_run_once'],
'job_toggle': '暂停/恢复任务',
'job_sync': ACTION_LABELS['job_sync'],
'ops_ping_db': ACTION_LABELS['ops_ping_db'],
'ops_ping_redis': ACTION_LABELS['ops_ping_redis'],
'prod_check_wizard': ACTION_LABELS['prod_check_wizard'],
}
CAPABILITY_HINT_LABELS = {
'app_run': '直接启动',
'app_run_wizard': '打开启动向导',
'cache_clear_wizard': '清理向导',
'cache_warmup': '执行缓存预热',
'completion_install': '安装补全',
'config_sync': '刷新参数缓存',
'crypto_keygen': '密钥生成',
'crypto_rotate_dry_run': '执行轮换预演',
'db_init_dry_run': '初始化预演',
'db_upgrade_wizard': '打开升级向导',
'gen_export_dry_run': '导出预演',
'gen_export_wizard': '导出向导',
'gen_import_wizard': '导入向导',
'gen_sync_db': '同步表结构',
'job_run_once': '执行一次',
'job_toggle': '暂停/恢复',
'job_sync': '同步调度',
'ops_ping_db': '数据库探活',
'ops_ping_redis': 'Redis 探活',
'prod_check_wizard': '打开生产巡检向导',
}
WORKSPACE_LABELS = {
'current_section': '当前分区',
'menu': '菜单',
'overview': '概览',
'record': '记录',
'section': '分区',
'shortcut': '快捷键',
'status': '状态',
}
WORKSPACE_TITLES = {
'action_feedback': '【执行反馈】',
'detail_content': '详情内容',
'key_fields': '【关键字段】',
'key_info': '【关键信息】',
}
WORKSPACE_EMPTY_TEXTS = {
'actions': '暂无可执行动作',
'detail': '暂无详情',
'key_info': '暂无关键信息',
}
STATE_SECTION_TITLES = {
'detail': '## 补充说明',
'diagnostic': '## 诊断线索',
'error': '## 错误摘要',
'status': '## 当前状态',
'suggestion': '## 下一步',
}
ACTION_NOTIFICATION_COPY = {
'empty_line': '当前记录没有可执行的低风险动作',
'title': 'TUI 动作',
'unavailable_message': '当前页面没有可执行的对应快捷动作',
}
BROWSER_ACTION_PANEL_COPY = {
'action_section_title': '## 可执行动作',
'operation_section_title': '## 浏览操作',
'recent_action_section_title': '## 最近动作反馈',
}
COMMAND_HINT_TITLES = {
'command': '## 推荐命令',
'guide': '## 使用说明',
'scenario': '## 适用场景',
}
SIGNAL_RAIL_COPY = {
'empty': '暂无实时信号',
'title': '系统信号带',
}
METRIC_COPY = {
'hint_label': '说明',
'label': '指标',
'value_label': '数值',
}
ACTION_HINT_COPY = {
'browser_default': '当前页面以浏览为主。{interaction_hint}',
'browser_templates': {
'cache': '建议先核对 Redis 概览与键值样本,再决定预热或进入清理向导。{interaction_hint}',
'configs': '建议先看高风险配置,再决定是否刷新参数缓存。{interaction_hint}',
'gen': '建议先看生成前校验、同步预检查与代码预览,再决定是否进入导入向导、同步表结构或进入导出向导。{interaction_hint}',
'jobs': '建议先看失败聚合,再决定执行一次、暂停恢复或同步调度。{interaction_hint}',
},
'detail_default': '当前页面以查看分区为主。{interaction_hint}',
'detail_templates': {
'app': '建议先确认环境映射、应用配置、启动前检查、补全诊断和路由状态,再决定是安装补全、直接启动应用还是进入启动向导。{interaction_hint}',
'crypto': '建议先确认运行校验、公钥身份和兼容版本,再决定是否生成新密钥或执行轮换预演。{interaction_hint}',
'database': '建议先确认 revision、Heads 和历史链路,再决定是否执行初始化预演或进入升级向导。{interaction_hint}',
'ops': '建议先确认数据库探活、Redis 探活、依赖版本和服务器资源,再决定是否进入生产巡检。{interaction_hint}',
},
'operation_hint_lines': [
'> [←/→] 切换焦点',
'> [J/K] 向上/向下滚动',
'> [PgUp/PgDn] 整页滚动',
'> [Home/End] 跳到首尾',
],
}
ACTION_FEEDBACK_COPY = {
'toast_prefix': '动作结果',
}
@@ -0,0 +1,133 @@
from cli.tui.copy.fragments import (
APP_BINDING_LABELS,
GENERAL_COPY,
INTERNAL_BINDING_LABELS,
NAVIGATION_DESCRIPTIONS,
STATUS_LABELS,
VIEW_LABELS,
)
class TuiNavigationCopyMixin:
"""
TUI 导航与基础标签文案混入。
"""
@staticmethod
def render_view_label(view_key: str) -> str:
"""
将内部视图标识转换为中文显示名称。
:param view_key: 视图标识
:return: 中文视图名称
"""
normalized_view = str(view_key).strip().lower()
return VIEW_LABELS.get(normalized_view, view_key)
@staticmethod
def render_status_label(status: str, fallback: str = '信息') -> str:
"""
将状态值转换为中文显示文本。
:param status: 原始状态值
:param fallback: 缺失时兜底文本
:return: 中文状态文本
"""
normalized_status = str(status).strip().lower()
if not normalized_status:
return fallback
return STATUS_LABELS.get(normalized_status, str(status).strip().upper())
@staticmethod
def render_status_code(status: str) -> str:
"""
将状态值转换为控制台风格状态码。
:param status: 原始状态值
:return: 状态码文本
"""
normalized_status = str(status).strip().lower()
status_code_mapping = {
'ok': 'SYS.OK',
'success': 'SYS.OK',
'healthy': 'SYS.OK',
'fail': 'SYS.FAIL',
'error': 'SYS.FAIL',
'down': 'SYS.FAIL',
'warn': 'SYS.WARN',
'warning': 'SYS.WARN',
'degraded': 'SYS.WARN',
'info': 'SYS.INFO',
}
return status_code_mapping.get(normalized_status, f'SYS.{normalized_status.upper() or "INFO"}')
@staticmethod
def render_navigation_description(view_key: str) -> str:
"""
获取指定视图的导航说明。
:param view_key: 视图标识
:return: 导航说明
"""
normalized_view = str(view_key).strip().lower()
return NAVIGATION_DESCRIPTIONS.get(normalized_view, '')
@staticmethod
def build_tui_command_help() -> str:
"""
构建 `shierfeng tui` 命令帮助文案。
:return: 命令帮助文案
"""
return GENERAL_COPY['tui_command_help']
@staticmethod
def build_missing_dependency_message() -> str:
"""
构建 TUI 可选依赖缺失时的提示消息。
:return: 缺依赖提示消息
"""
return GENERAL_COPY['tui_missing_dependency_message']
@staticmethod
def build_missing_dependency_hint() -> str:
"""
构建 TUI 可选依赖缺失时的恢复建议。
:return: 恢复建议文案
"""
return GENERAL_COPY['tui_missing_dependency_hint']
@staticmethod
def build_app_binding_label(binding_key: str) -> str:
"""
根据绑定标识构建应用级快捷键标签文案。
:param binding_key: 绑定标识
:return: 快捷键标签文案
"""
normalized_key = str(binding_key).strip().lower()
return APP_BINDING_LABELS.get(normalized_key, normalized_key)
@staticmethod
def build_confirm_binding_label(binding_key: str) -> str:
"""
根据确认弹窗绑定标识构建快捷键标签文案。
:param binding_key: 绑定标识
:return: 快捷键标签文案
"""
normalized_key = str(binding_key).strip().lower()
return INTERNAL_BINDING_LABELS.get(f'confirm_{normalized_key}', normalized_key)
@staticmethod
def build_internal_binding_label(binding_key: str) -> str:
"""
根据内部交互绑定标识构建快捷键标签文案。
:param binding_key: 绑定标识
:return: 快捷键标签文案
"""
normalized_key = str(binding_key).strip().lower()
return INTERNAL_BINDING_LABELS.get(normalized_key, normalized_key)
@@ -0,0 +1,593 @@
from cli.tui.copy.fragments import (
ACTION_HINT_COPY,
BROWSER_ACTION_PANEL_COPY,
BROWSER_EMPTY_RECORD_COPY,
BROWSER_LOADING_COPY,
DASHBOARD_HERO_COPY,
DETAIL_EMPTY_SECTION_COPY,
GENERAL_COPY,
METRIC_COPY,
SIGNAL_RAIL_COPY,
STATE_SECTION_TITLES,
STATE_SUGGESTIONS,
STATUS_PANEL_COPY,
WORKSPACE_EMPTY_TEXTS,
WORKSPACE_LABELS,
WORKSPACE_TITLES,
)
class TuiWorkspaceCopyMixin:
"""
TUI 工作区与状态文案混入。
"""
@staticmethod
def build_workspace_label(label_key: str) -> str:
"""
根据工作台标签标识构建文案。
:param label_key: 标签标识
:return: 标签文案
"""
normalized_key = str(label_key).strip().lower()
return WORKSPACE_LABELS.get(normalized_key, normalized_key)
@staticmethod
def build_workspace_title(title_key: str) -> str:
"""
根据工作台标题标识构建文案。
:param title_key: 标题标识
:return: 标题文案
"""
normalized_key = str(title_key).strip().lower()
return WORKSPACE_TITLES.get(normalized_key, normalized_key)
@staticmethod
def build_workspace_empty_text(text_key: str) -> str:
"""
根据工作台空态标识构建文案。
:param text_key: 空态标识
:return: 空态文案
"""
normalized_key = str(text_key).strip().lower()
return WORKSPACE_EMPTY_TEXTS.get(normalized_key, normalized_key)
@staticmethod
def build_status_panel_empty_text() -> str:
"""
构建状态面板空态提示文案。
:return: 空态提示文案
"""
return STATUS_PANEL_COPY['empty']
@staticmethod
def build_signal_rail_empty_text() -> str:
"""
构建信号带空态提示文案。
:return: 空态提示文案
"""
return SIGNAL_RAIL_COPY['empty']
@staticmethod
def build_more_detail_hint() -> str:
"""
构建查看更多提示文案。
:return: 提示文案
"""
return GENERAL_COPY['more_detail_hint']
@staticmethod
def build_empty_state_suggestion() -> str:
"""
构建通用空态建议文案。
:return: 建议文案
"""
return STATE_SUGGESTIONS['empty']
@staticmethod
def build_loading_state_suggestion() -> str:
"""
构建通用加载态建议文案。
:return: 建议文案
"""
return STATE_SUGGESTIONS['loading']
@staticmethod
def build_failure_state_suggestion() -> str:
"""
构建通用失败态建议文案。
:return: 建议文案
"""
return STATE_SUGGESTIONS['failure']
@staticmethod
def build_dashboard_failure_suggestion() -> str:
"""
构建首页失败态建议文案。
:return: 建议文案
"""
return STATE_SUGGESTIONS['dashboard_failure']
@staticmethod
def build_dashboard_empty_suggestion() -> str:
"""
构建首页空态建议文案。
:return: 建议文案
"""
return STATE_SUGGESTIONS['dashboard_empty']
@staticmethod
def build_state_section_title(title_key: str) -> str:
"""
根据状态区块标识构建标题文案。
:param title_key: 区块标识
:return: 标题文案
"""
normalized_key = str(title_key).strip().lower()
return STATE_SECTION_TITLES.get(normalized_key, normalized_key)
@staticmethod
def build_dashboard_hero_title() -> str:
"""
构建首页 Hero 标题文案。
:return: 标题文案
"""
return DASHBOARD_HERO_COPY['title']
@staticmethod
def build_dashboard_hero_subtitle() -> str:
"""
构建首页 Hero 副标题文案。
:return: 副标题文案
"""
return DASHBOARD_HERO_COPY['subtitle']
@staticmethod
def build_browser_empty_record_copy(field_key: str) -> str:
"""
根据字段标识构建浏览页空记录文案。
:param field_key: 字段标识
:return: 文案
"""
normalized_key = str(field_key).strip().lower()
return BROWSER_EMPTY_RECORD_COPY.get(normalized_key, normalized_key)
@staticmethod
def build_browser_loading_copy(field_key: str) -> str:
"""
根据字段标识构建浏览页加载占位文案。
:param field_key: 字段标识
:return: 文案
"""
normalized_key = str(field_key).strip().lower()
return BROWSER_LOADING_COPY.get(normalized_key, normalized_key)
@staticmethod
def build_detail_empty_section_copy(field_key: str) -> str:
"""
根据字段标识构建详情页空态文案。
:param field_key: 字段标识
:return: 文案
"""
normalized_key = str(field_key).strip().lower()
return DETAIL_EMPTY_SECTION_COPY.get(normalized_key, normalized_key)
@staticmethod
def build_refresh_page_suggestion(page_name: str, detail: str) -> str:
"""
构建详情页场景下的统一建议操作文案。
:param page_name: 页面名称
:param detail: 后续动作描述
:return: 建议文案
"""
return f'可按 [R] 刷新,或进入{page_name}页面{detail}'
@staticmethod
def build_dashboard_page_suggestion(page_name: str, detail: str) -> str:
"""
构建首页总览面板场景下的统一建议操作文案。
:param page_name: 页面名称
:param detail: 后续动作描述
:return: 建议文案
"""
return f'按 [R] 刷新,或进入{page_name}页面{detail}'
@staticmethod
def build_unavailable_record_title(resource_name: str) -> str:
"""
构建浏览页失败兜底记录标题。
:param resource_name: 资源名称
:return: 标题文本
"""
return f'{resource_name}数据暂不可用'
@staticmethod
def build_load_failure_section_title(resource_name: str) -> str:
"""
构建浏览页失败兜底分区标题。
:param resource_name: 资源名称
:return: 分区标题
"""
return f'{resource_name}加载失败'
@staticmethod
def build_empty_record_title(resource_name: str) -> str:
"""
构建浏览页空记录标题。
:param resource_name: 资源名称
:return: 标题文本
"""
return f'暂无{resource_name}'
@staticmethod
def build_unavailable_subtitle(resource_name: str, message: str) -> str:
"""
构建浏览页数据不可用副标题。
:param resource_name: 资源名称
:param message: 错误摘要
:return: 副标题文本
"""
return f'{resource_name}数据不可用:{message}'
@staticmethod
def build_empty_record_summary(detail: str) -> str:
"""
构建浏览页空记录摘要。
:param detail: 摘要说明
:return: 摘要文本
"""
return detail
@staticmethod
def build_loaded_collection_subtitle(count: int, unit: str, detail: str) -> str:
"""
构建浏览页“已加载”副标题。
:param count: 数量
:param unit: 单位
:param detail: 补充说明
:return: 副标题文本
"""
return f'已加载 {count} {unit},{detail}'
@staticmethod
def build_summary_with_message(summary: str, message: str) -> str:
"""
构建带结果摘要补充的副标题。
:param summary: 主摘要
:param message: 结果消息
:return: 副标题文本
"""
return f'{summary} | {message}'
@staticmethod
def build_count_detail_subtitle(prefix: str, count: int, unit: str, suffix: str) -> str:
"""
构建带数量的详情页副标题。
:param prefix: 前缀文本
:param count: 数量
:param unit: 数量单位
:param suffix: 后缀文本
:return: 副标题文本
"""
return f'{prefix} {count} {unit}{suffix}'
@staticmethod
def build_value_detail_subtitle(prefix: str, value: str, suffix: str) -> str:
"""
构建带单值信息的详情页副标题。
:param prefix: 前缀文本
:param value: 值文本
:param suffix: 后缀文本
:return: 副标题文本
"""
return f'{prefix} {value}{suffix}'
@staticmethod
def build_workspace_hero_lines(
*,
view_label: str,
title: str,
subtitle: str,
env: str,
summary: str,
refreshed_at: str,
shortcut_hint: str,
) -> list[str]:
"""
构建工作区顶部摘要文本行。
:param view_label: 当前页面显示名称
:param title: 页面标题
:param subtitle: 页面副标题
:param env: 当前环境
:param summary: 页面摘要
:param refreshed_at: 刷新时间
:param shortcut_hint: 快捷键提示
:return: 文本行列表
"""
return [
f'[{view_label} 控制台]',
title,
subtitle,
'',
f'运行环境 · {env}',
f'当前页面 · {view_label}',
f'运行摘要 · {summary}',
f'操作提示 · {shortcut_hint}',
f'最近刷新 · {refreshed_at}',
]
@staticmethod
def build_navigation_item_lines(index: int, label: str, shortcut: str, description: str) -> list[str]:
"""
构建左侧导航项文案。
:param index: 导航索引
:param label: 导航标题
:param shortcut: 快捷键
:param description: 导航说明
:return: 文本行列表
"""
return [
f'▌ {WORKSPACE_LABELS["menu"]} {index + 1:02d} · {label}',
f'│ {WORKSPACE_LABELS["shortcut"]} [{shortcut.upper()}] · {description}',
]
@staticmethod
def build_section_item_lines(index: int, title: str, status_badge: str, preview: str) -> list[str]:
"""
构建详情页分区导航项文案。
:param index: 分区索引
:param title: 分区标题
:param status_badge: 状态徽标
:param preview: 预览文本
:return: 文本行列表
"""
return [
f'▌ {WORKSPACE_LABELS["section"]} {index + 1:02d} · {title}',
f'│ {status_badge} {preview}',
]
@staticmethod
def build_record_item_lines(index: int, title: str, status_badge: str, summary: str) -> list[str]:
"""
构建浏览页记录导航项文案。
:param index: 记录索引
:param title: 记录标题
:param status_badge: 状态徽标
:param summary: 记录摘要
:return: 文本行列表
"""
return [
f'▌ {WORKSPACE_LABELS["record"]} {index + 1:02d} · {title}',
f'│ {status_badge} {summary}',
]
@staticmethod
def build_section_detail_lines(title: str, status_label: str, status_badge: str, body: str) -> list[str]:
"""
构建详情页右侧分区内容文案。
:param title: 分区标题
:param status_label: 分区状态
:param status_badge: 状态徽标
:param body: 主体文本
:return: 文本行列表
"""
return [
f'{status_badge} {title}',
f'{WORKSPACE_LABELS["status"]} · {status_label}',
'',
body,
]
@staticmethod
def build_browser_action_panel_lines(action_lines: list[str], feedback_lines: list[str]) -> list[str]:
"""
构建浏览页动作面板文案。
:param action_lines: 可执行动作文本
:param feedback_lines: 最近动作反馈文本
:return: 文本行列表
"""
lines = [
BROWSER_ACTION_PANEL_COPY['action_section_title'],
*[f'> {line}' for line in action_lines],
'',
BROWSER_ACTION_PANEL_COPY['operation_section_title'],
]
lines.extend(ACTION_HINT_COPY['operation_hint_lines'])
if feedback_lines:
lines.extend(
[
'',
BROWSER_ACTION_PANEL_COPY['recent_action_section_title'],
*[f'> {line}' for line in feedback_lines],
]
)
return lines
@staticmethod
def build_status_panel_text(title: str, status_code: str, status_label: str, body: str) -> str:
"""
构建状态面板渲染文本。
:param title: 面板标题
:param status_code: 状态码
:param status_label: 状态标签
:param body: 面板正文
:return: 渲染文本
"""
return f'{status_code} {title}\n{WORKSPACE_LABELS["status"]} · {status_label}\n\n{body}'
@staticmethod
def build_metric_panel_text(title: str, value: str, status_code: str, status_label: str, hint: str) -> str:
"""
构建指标卡渲染文本。
:param title: 指标标题
:param value: 指标值
:param status_code: 状态码
:param status_label: 状态标签
:param hint: 提示文本
:return: 渲染文本
"""
return (
f'{METRIC_COPY["label"]} · {title}\n'
f'────────────────────────\n'
f'{METRIC_COPY["value_label"]} · {value}\n'
f'{WORKSPACE_LABELS["status"]} · {status_code} / {status_label}\n'
f'{METRIC_COPY["hint_label"]} · {hint}'
)
@staticmethod
def build_signal_rail_text(pulse: str, body: str) -> str:
"""
构建首页信号带渲染文本。
:param pulse: 当前脉冲字符
:param body: 主体文本
:return: 渲染文本
"""
return '\n'.join(
[
f'{SIGNAL_RAIL_COPY["title"]} {pulse}',
'────────────────────────',
body or SIGNAL_RAIL_COPY['empty'],
]
)
@staticmethod
def build_workspace_header_lines(
*,
env: str,
view_label: str,
timestamp: str,
shortcut_hint: str,
) -> list[str]:
"""
构建工作区顶部状态栏文本行。
:param env: 当前环境
:param view_label: 当前页面显示名称
:param timestamp: 当前时间
:param shortcut_hint: 快捷键提示
:return: 文本行列表
"""
return [
f'ShiErFeng 控制台 · 环境 {env.upper()} · 页面 {view_label}',
f'快捷键 · {shortcut_hint} 时间 {timestamp}',
]
@staticmethod
def build_dashboard_signal_lines(
*,
status_track: str,
fail_count: int,
warn_count: int,
ok_count: int,
total_count: int,
navigation_shortcut_hint: str,
) -> list[str]:
"""
构建首页信号带文案。
:param status_track: 面板状态轨迹
:param fail_count: 失败数量
:param warn_count: 警告数量
:param ok_count: 正常数量
:param total_count: 总数量
:param navigation_shortcut_hint: 页面快捷键提示
:return: 文本行列表
"""
return [
f'面板轨迹 · {status_track or "-"}',
f'风险分布 · 失败 {fail_count:02d} 警告 {warn_count:02d} 正常 {ok_count:02d} 合计 {total_count:02d}',
f'快捷入口 · 页面 {navigation_shortcut_hint}',
]
@staticmethod
def build_dashboard_summary_text(total_count: int, ok_count: int, warn_count: int, fail_count: int) -> str:
"""
构建首页摘要文本。
:param total_count: 面板总数
:param ok_count: 正常数量
:param warn_count: 警告数量
:param fail_count: 失败数量
:return: 摘要文本
"""
posture = '存在风险' if fail_count else '需要关注' if warn_count else '运行稳定'
return (
f'当前态势:{posture}。共 {total_count} 个面板,正常 {ok_count} 个,'
f'警告 {warn_count} 个,失败 {fail_count} 个。'
)
@staticmethod
def build_detail_summary_text(total_count: int, ok_count: int, warn_count: int, fail_count: int) -> str:
"""
构建详情页摘要文本。
:param total_count: 分区总数
:param ok_count: 正常数量
:param warn_count: 警告数量
:param fail_count: 失败数量
:return: 摘要文本
"""
return (
f'当前页共 {total_count} 个分区,正常 {ok_count} 个,警告 {warn_count} 个,失败 {fail_count} 个。'
'左侧上下切页,左右切换当前焦点区域。'
)
@staticmethod
def build_browser_summary_text(
total_count: int,
ok_count: int,
warn_count: int,
fail_count: int,
action_hint: str,
) -> str:
"""
构建浏览页摘要文本。
:param total_count: 记录总数
:param ok_count: 正常数量
:param warn_count: 警告数量
:param fail_count: 失败数量
:param action_hint: 动作提示文案
:return: 摘要文本
"""
return (
f'当前页共 {total_count} 条记录,正常 {ok_count} 条,警告 {warn_count} 条,失败 {fail_count} 条。'
f'切换记录后,右侧会联动展示概览与分区详情。{action_hint}'
)