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

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,152 @@
from dataclasses import dataclass
from typing import Any
from cli.context import CliContext
from cli.wizard.base import BaseLiveExecCliWizardFlow
@dataclass(frozen=True)
class AppRunWizardSelection:
"""
`wizard app-run` 向导采集结果。
:param env: 运行环境
:param run_doctor: 启动前是否先执行应用检查
"""
env: str
run_doctor: bool
class AppRunWizardFlow(BaseLiveExecCliWizardFlow[AppRunWizardSelection]):
"""
`wizard app-run` 向导流程。
:param doctor_payload: 启动前检查结果缓存
"""
wizard_name = 'wizard app-run'
preview_title = 'wizard app-run preview'
failure_message = '应用启动向导执行失败'
def collect_selection(self) -> AppRunWizardSelection:
"""
采集应用启动向导参数。
:return: 向导采集结果
"""
env = self.prompt_service.prompt_env('dev')
run_doctor = self.prompt_service.prompt_confirm('启动前是否先执行应用检查', default_value=True)
return AppRunWizardSelection(env=env, run_doctor=run_doctor)
def prepare_context(self, selection: AppRunWizardSelection, output: str) -> CliContext:
"""
构建应用启动向导上下文。
:param selection: 向导采集结果
:param output: 输出格式
:return: CLI 上下文
"""
del output
return self.build_readonly_context(selection.env, 'text')
def build_preview_summary(self, selection: AppRunWizardSelection) -> dict[str, Any]:
"""
构建应用启动预览摘要。
:param selection: 向导采集结果
:return: 预览摘要
"""
return {
'env': selection.env,
'run_doctor': str(selection.run_doctor).lower(),
'doctor_ok': '-' if self.doctor_payload is None else str(self.doctor_payload.get('ok', False)).lower(),
}
def build_preview_command(self, selection: AppRunWizardSelection) -> list[str]:
"""
构建应用启动预览命令。
:param selection: 向导采集结果
:return: 用户视角命令参数
"""
return ['shierfeng', 'app', 'run', f'--env={selection.env}']
def build_preview_notes(self, selection: AppRunWizardSelection) -> list[str] | None:
"""
构建应用启动预览附加说明。
:param selection: 向导采集结果
:return: 预览附加说明
"""
del selection
notes: list[str] = []
if isinstance(self.doctor_payload, dict) and not self.doctor_payload.get('ok', False):
notes.append(self.doctor_payload.get('message', '启动前检查未通过'))
return notes or None
def confirm_prompt(self, selection: AppRunWizardSelection) -> str:
"""
返回应用启动最终确认提示。
:param selection: 向导采集结果
:return: 确认提示
"""
del selection
return '确认启动应用吗'
def confirm_default_value(self, selection: AppRunWizardSelection) -> bool:
"""
返回应用启动确认默认值。
:param selection: 向导采集结果
:return: 默认确认值
"""
del selection
return bool(self.doctor_payload is None or self.doctor_payload.get('ok', False))
def build_execute_arguments(self, selection: AppRunWizardSelection, output: str) -> list[str]:
"""
构建应用启动内部 CLI 参数。
:param selection: 向导采集结果
:param output: 输出格式
:return: 内部 CLI 参数
"""
del output
return ['app', 'run', f'--env={selection.env}']
def __init__(self) -> None:
"""
初始化应用启动向导流程。
:return: None
"""
super().__init__()
self.doctor_payload: dict[str, Any] | None = None
def prepare_execution_state(self, selection: AppRunWizardSelection, output: str) -> None:
"""
在预览与确认前准备启动前检查结果。
:param selection: 向导采集结果
:param output: 输出格式
:return: None
"""
del output
self.doctor_payload = None
if selection.run_doctor:
doctor_result = self.run_nested_command(
'app', 'doctor', f'--env={selection.env}', '--output=json', parse_json=True
)
payload = getattr(doctor_result, 'payload', None)
self.doctor_payload = payload if isinstance(payload, dict) else None
def run_app_run_wizard() -> None:
"""
执行 `wizard app-run` 向导。
:return: None
"""
AppRunWizardFlow().run('text')
@@ -0,0 +1,213 @@
from dataclasses import dataclass
from cli.context import CliContext, OutputOption
from cli.wizard.base import BaseCliWizardFlow
@dataclass(frozen=True)
class CacheClearWizardSelection:
"""
`wizard cache-clear` 向导采集结果。
:param env: 运行环境
:param mode: 清理模式
:param cache_name: 缓存名称前缀
:param cache_key: 缓存键名关键字
:param dry_run: 是否演练执行
:param allow_prod: 是否允许生产环境执行
"""
env: str
mode: str
cache_name: str
cache_key: str
dry_run: bool
allow_prod: bool
class CacheClearWizardFlow(BaseCliWizardFlow[CacheClearWizardSelection]):
"""
`wizard cache-clear` 向导流程。
:param default_env: 默认环境
:param default_mode: 默认清理模式
:param default_cache_name: 默认缓存名称前缀
:param default_cache_key: 默认缓存键名关键字
:param default_dry_run: 默认是否先执行 dry-run
"""
wizard_name = 'wizard cache-clear'
preview_title = 'wizard cache-clear preview'
failure_message = '缓存清理向导执行失败'
def __init__(
self,
*,
default_env: str = 'dev',
default_mode: str = 'cache-name',
default_cache_name: str = '',
default_cache_key: str = '',
default_dry_run: bool = True,
) -> None:
"""
初始化缓存清理向导流程。
:param default_env: 默认环境
:param default_mode: 默认清理模式
:param default_cache_name: 默认缓存名称前缀
:param default_cache_key: 默认缓存键名关键字
:param default_dry_run: 默认是否先执行 dry-run
:return: None
"""
self.default_env = default_env
self.default_mode = default_mode
self.default_cache_name = default_cache_name
self.default_cache_key = default_cache_key
self.default_dry_run = default_dry_run
def collect_selection(self) -> CacheClearWizardSelection:
"""
采集缓存清理向导参数。
:return: 向导采集结果
"""
env = self.prompt_service.prompt_env(self.default_env)
mode = self.prompt_service.prompt_choice(
'清理模式',
['cache-name', 'cache-key', 'all'],
self.default_mode,
)
cache_name = ''
cache_key = ''
if mode == 'cache-name':
cache_name = self.prompt_service.prompt_required_text('缓存名称前缀', self.default_cache_name)
elif mode == 'cache-key':
cache_key = self.prompt_service.prompt_required_text('缓存键名关键字', self.default_cache_key)
else:
self.prompt_service.prompt_optional_text('当前将清理全部缓存,按回车继续', '')
dry_run = self.prompt_service.prompt_confirm('是否先执行 dry-run 预演', default_value=self.default_dry_run)
allow_prod = (
self.prompt_service.prompt_confirm('当前为 prod 环境,是否允许继续执行', default_value=False)
if env == 'prod'
else False
)
return CacheClearWizardSelection(
env=env,
mode=mode,
cache_name=cache_name,
cache_key=cache_key,
dry_run=dry_run,
allow_prod=allow_prod,
)
def prepare_context(self, selection: CacheClearWizardSelection, output: OutputOption) -> CliContext:
"""
构建缓存清理向导上下文。
:param selection: 向导采集结果
:param output: 输出格式
:return: CLI 上下文
"""
return self.build_regular_context(
selection.env,
output,
allow_prod=selection.allow_prod,
yes=True,
dry_run=selection.dry_run,
)
def build_preview_summary(self, selection: CacheClearWizardSelection) -> dict[str, str]:
"""
构建缓存清理预览摘要。
:param selection: 向导采集结果
:return: 预览摘要
"""
return {
'env': selection.env,
'mode': selection.mode,
'cache_name': selection.cache_name or '-',
'cache_key': selection.cache_key or '-',
'dry_run': str(selection.dry_run).lower(),
'allow_prod': str(selection.allow_prod).lower(),
}
def build_preview_command(self, selection: CacheClearWizardSelection) -> list[str]:
"""
构建缓存清理预览命令。
:param selection: 向导采集结果
:return: 用户视角命令参数
"""
command = ['shierfeng', 'cache', 'clear', f'--env={selection.env}']
if selection.mode == 'cache-name':
command.append(f'--cache-name={selection.cache_name}')
elif selection.mode == 'cache-key':
command.append(f'--cache-key={selection.cache_key}')
else:
command.append('--all')
if selection.dry_run:
command.append('--dry-run')
if selection.allow_prod:
command.append('--allow-prod')
return command
def confirm_prompt(self, selection: CacheClearWizardSelection) -> str:
"""
返回缓存清理最终确认提示。
:param selection: 向导采集结果
:return: 确认提示
"""
del selection
return '确认执行缓存清理向导吗'
def build_execute_arguments(self, selection: CacheClearWizardSelection, output: OutputOption) -> list[str]:
"""
构建缓存清理内部 CLI 参数。
:param selection: 向导采集结果
:param output: 输出格式
:return: 内部 CLI 参数
"""
arguments = ['cache', 'clear', f'--env={selection.env}', f'--output={output}', '--yes']
if selection.mode == 'cache-name':
arguments.append(f'--cache-name={selection.cache_name}')
elif selection.mode == 'cache-key':
arguments.append(f'--cache-key={selection.cache_key}')
else:
arguments.append('--all')
if selection.dry_run:
arguments.append('--dry-run')
if selection.allow_prod:
arguments.append('--allow-prod')
return arguments
def run_cache_clear_wizard(
output: OutputOption = 'text',
*,
default_env: str = 'dev',
default_mode: str = 'cache-name',
default_cache_name: str = '',
default_cache_key: str = '',
default_dry_run: bool = True,
) -> None:
"""
执行 `wizard cache-clear` 向导。
:param output: 输出格式
:param default_env: 默认环境
:param default_mode: 默认清理模式
:param default_cache_name: 默认缓存名称前缀
:param default_cache_key: 默认缓存键关键字
:param default_dry_run: 默认是否执行 dry-run
:return: None
"""
CacheClearWizardFlow(
default_env=default_env,
default_mode=default_mode,
default_cache_name=default_cache_name,
default_cache_key=default_cache_key,
default_dry_run=default_dry_run,
).run(output)
@@ -0,0 +1,169 @@
from dataclasses import dataclass
from cli.context import CliContext, OutputOption
from cli.wizard.base import BaseCliWizardFlow
@dataclass(frozen=True)
class DbUpgradeWizardSelection:
"""
`wizard db-upgrade` 向导采集结果。
:param env: 运行环境
:param revision: 目标迁移版本
:param dry_run: 是否演练执行
:param allow_prod: 是否允许生产环境执行
"""
env: str
revision: str
dry_run: bool
allow_prod: bool
class DbUpgradeWizardFlow(BaseCliWizardFlow[DbUpgradeWizardSelection]):
"""
`wizard db-upgrade` 向导流程。
:param default_env: 默认环境
:param default_revision: 默认目标 revision
:param default_dry_run: 默认是否先执行 dry-run
"""
wizard_name = 'wizard db-upgrade'
preview_title = 'wizard db-upgrade preview'
failure_message = '数据库升级向导执行失败'
def __init__(
self,
*,
default_env: str = 'dev',
default_revision: str = 'head',
default_dry_run: bool = True,
) -> None:
"""
初始化数据库升级向导流程。
:param default_env: 默认环境
:param default_revision: 默认目标 revision
:param default_dry_run: 默认是否先执行 dry-run
:return: None
"""
self.default_env = default_env
self.default_revision = default_revision
self.default_dry_run = default_dry_run
def collect_selection(self) -> DbUpgradeWizardSelection:
"""
采集数据库升级向导参数。
:return: 向导采集结果
"""
env = self.prompt_service.prompt_env(self.default_env)
revision = self.prompt_service.prompt_required_text('目标迁移版本', self.default_revision)
dry_run = self.prompt_service.prompt_confirm('是否先执行 dry-run 预演', default_value=self.default_dry_run)
allow_prod = (
self.prompt_service.prompt_confirm('当前为 prod 环境,是否允许继续执行', default_value=False)
if env == 'prod'
else False
)
return DbUpgradeWizardSelection(env=env, revision=revision, dry_run=dry_run, allow_prod=allow_prod)
def prepare_context(self, selection: DbUpgradeWizardSelection, output: OutputOption) -> CliContext:
"""
构建数据库升级向导上下文。
:param selection: 向导采集结果
:param output: 输出格式
:return: CLI 上下文
"""
return self.build_regular_context(
selection.env,
output,
allow_prod=selection.allow_prod,
yes=True,
dry_run=selection.dry_run,
)
def build_preview_summary(self, selection: DbUpgradeWizardSelection) -> dict[str, str]:
"""
构建数据库升级预览摘要。
:param selection: 向导采集结果
:return: 预览摘要
"""
return {
'env': selection.env,
'revision': selection.revision,
'dry_run': str(selection.dry_run).lower(),
'allow_prod': str(selection.allow_prod).lower(),
}
def build_preview_command(self, selection: DbUpgradeWizardSelection) -> list[str]:
"""
构建数据库升级预览命令。
:param selection: 向导采集结果
:return: 用户视角命令参数
"""
command = ['shierfeng', 'db', 'upgrade', f'--env={selection.env}', f'--revision={selection.revision}']
if selection.dry_run:
command.append('--dry-run')
if selection.allow_prod:
command.append('--allow-prod')
return command
def confirm_prompt(self, selection: DbUpgradeWizardSelection) -> str:
"""
返回数据库升级最终确认提示。
:param selection: 向导采集结果
:return: 确认提示
"""
del selection
return '确认执行数据库升级向导吗'
def build_execute_arguments(self, selection: DbUpgradeWizardSelection, output: OutputOption) -> list[str]:
"""
构建数据库升级内部 CLI 参数。
:param selection: 向导采集结果
:param output: 输出格式
:return: 内部 CLI 参数
"""
arguments = [
'db',
'upgrade',
f'--env={selection.env}',
f'--output={output}',
f'--revision={selection.revision}',
'--yes',
]
if selection.dry_run:
arguments.append('--dry-run')
if selection.allow_prod:
arguments.append('--allow-prod')
return arguments
def run_db_upgrade_wizard(
output: OutputOption = 'text',
*,
default_env: str = 'dev',
default_revision: str = 'head',
default_dry_run: bool = True,
) -> None:
"""
执行 `wizard db-upgrade` 向导。
:param output: 输出格式
:param default_env: 默认环境
:param default_revision: 默认目标 revision
:param default_dry_run: 默认是否先 dry-run
:return: None
"""
DbUpgradeWizardFlow(
default_env=default_env,
default_revision=default_revision,
default_dry_run=default_dry_run,
).run(output)
@@ -0,0 +1,239 @@
from dataclasses import dataclass
import typer
from cli.context import CliContext, OutputOption
from cli.wizard.base import BaseCliWizardFlow
@dataclass(frozen=True)
class GenExportWizardSelection:
"""
`wizard gen-export` 向导采集结果。
:param env: 运行环境
:param table_names: 业务表名称列表
:param mode: 导出模式
:param output_file: zip 导出目标文件路径
:param dry_run: 是否演练执行
:param allow_prod: 是否允许生产环境执行
"""
env: str
table_names: list[str]
mode: str
output_file: str
dry_run: bool
allow_prod: bool
class GenExportWizardFlow(BaseCliWizardFlow[GenExportWizardSelection]):
"""
`wizard gen-export` 向导流程。
:param default_env: 默认环境
:param default_table_names: 默认业务表名称列表文本
:param default_mode: 默认导出模式
:param default_output_file: 默认 zip 导出目标文件路径
:param default_dry_run: 默认是否先执行 dry-run
"""
wizard_name = 'wizard gen-export'
preview_title = 'wizard gen-export preview'
failure_message = '代码导出向导执行失败'
def __init__(
self,
*,
default_env: str = 'dev',
default_table_names: str = '',
default_mode: str = 'zip',
default_output_file: str = '',
default_dry_run: bool = True,
) -> None:
"""
初始化代码导出向导流程。
:param default_env: 默认环境
:param default_table_names: 默认业务表名称列表文本
:param default_mode: 默认导出模式
:param default_output_file: 默认 zip 导出目标文件路径
:param default_dry_run: 默认是否先执行 dry-run
:return: None
"""
self.default_env = default_env
self.default_table_names = default_table_names
self.default_mode = default_mode
self.default_output_file = default_output_file
self.default_dry_run = default_dry_run
def collect_selection(self) -> GenExportWizardSelection:
"""
采集代码导出向导参数。
:return: 向导采集结果
"""
env = self.prompt_service.prompt_env(self.default_env)
raw_table_names = self.prompt_service.prompt_required_text(
'业务表名称列表(多个表请使用逗号分隔)',
self.default_table_names,
)
table_names = self.parse_table_names(raw_table_names)
while not table_names:
typer.echo('至少需要输入一个业务表名称,请重新输入。')
raw_table_names = self.prompt_service.prompt_required_text(
'业务表名称列表(多个表请使用逗号分隔)',
self.default_table_names,
)
table_names = self.parse_table_names(raw_table_names)
mode = self.prompt_service.prompt_choice('导出模式', ['zip', 'local'], self.default_mode)
output_file = ''
if mode == 'zip':
output_file = self.prompt_service.prompt_optional_text(
'zip 导出目标文件路径(留空则使用默认文件名)',
self.default_output_file,
)
dry_run = self.prompt_service.prompt_confirm('是否先执行 dry-run 预演', default_value=self.default_dry_run)
allow_prod = (
self.prompt_service.prompt_confirm('当前为 prod 环境,是否允许继续执行', default_value=False)
if env == 'prod'
else False
)
return GenExportWizardSelection(
env=env,
table_names=table_names,
mode=mode,
output_file=output_file,
dry_run=dry_run,
allow_prod=allow_prod,
)
def prepare_context(self, selection: GenExportWizardSelection, output: OutputOption) -> CliContext:
"""
构建代码导出向导上下文。
:param selection: 向导采集结果
:param output: 输出格式
:return: CLI 上下文
"""
return self.build_regular_context(
selection.env,
output,
allow_prod=selection.allow_prod,
yes=True,
dry_run=selection.dry_run,
)
def build_preview_summary(self, selection: GenExportWizardSelection) -> dict[str, str]:
"""
构建代码导出预览摘要。
:param selection: 向导采集结果
:return: 预览摘要
"""
return {
'env': selection.env,
'table_names': ','.join(selection.table_names),
'mode': selection.mode,
'output_file': selection.output_file or '-',
'dry_run': str(selection.dry_run).lower(),
'allow_prod': str(selection.allow_prod).lower(),
}
def build_preview_command(self, selection: GenExportWizardSelection) -> list[str]:
"""
构建代码导出预览命令。
:param selection: 向导采集结果
:return: 用户视角命令参数
"""
command = [
'shierfeng',
'gen',
'export',
*selection.table_names,
f'--env={selection.env}',
f'--mode={selection.mode}',
]
if selection.output_file:
command.append(f'--output-file={selection.output_file}')
if selection.dry_run:
command.append('--dry-run')
if selection.allow_prod:
command.append('--allow-prod')
return command
def confirm_prompt(self, selection: GenExportWizardSelection) -> str:
"""
返回代码导出最终确认提示。
:param selection: 向导采集结果
:return: 确认提示
"""
del selection
return '确认执行代码导出向导吗'
def build_execute_arguments(self, selection: GenExportWizardSelection, output: OutputOption) -> list[str]:
"""
构建代码导出内部 CLI 参数。
:param selection: 向导采集结果
:param output: 输出格式
:return: 内部 CLI 参数
"""
arguments = [
'gen',
'export',
*selection.table_names,
f'--env={selection.env}',
f'--output={output}',
f'--mode={selection.mode}',
'--yes',
]
if selection.output_file:
arguments.append(f'--output-file={selection.output_file}')
if selection.dry_run:
arguments.append('--dry-run')
if selection.allow_prod:
arguments.append('--allow-prod')
return arguments
@staticmethod
def parse_table_names(raw_value: str) -> list[str]:
"""
将逗号分隔的业务表名称文本解析为列表。
:param raw_value: 原始输入文本
:return: 去空白后的业务表名称列表
"""
return [table_name.strip() for table_name in raw_value.split(',') if table_name.strip()]
def run_gen_export_wizard(
output: OutputOption = 'text',
*,
default_env: str = 'dev',
default_table_names: str = '',
default_mode: str = 'zip',
default_output_file: str = '',
default_dry_run: bool = True,
) -> None:
"""
执行 `wizard gen-export` 向导。
:param output: 输出格式
:param default_env: 默认环境
:param default_table_names: 默认业务表名称列表文本
:param default_mode: 默认导出模式
:param default_output_file: 默认 zip 导出目标文件路径
:param default_dry_run: 默认是否先 dry-run
:return: None
"""
GenExportWizardFlow(
default_env=default_env,
default_table_names=default_table_names,
default_mode=default_mode,
default_output_file=default_output_file,
default_dry_run=default_dry_run,
).run(output)
@@ -0,0 +1,208 @@
from dataclasses import dataclass
import typer
from cli.context import CliContext, OutputOption
from cli.wizard.base import BaseCliWizardFlow
@dataclass(frozen=True)
class GenImportWizardSelection:
"""
`wizard gen-import` 向导采集结果。
:param env: 运行环境
:param table_names: 待导入物理表名称列表
:param dry_run: 是否演练执行
:param allow_prod: 是否允许生产环境执行
"""
env: str
table_names: list[str]
dry_run: bool
allow_prod: bool
class GenImportWizardFlow(BaseCliWizardFlow[GenImportWizardSelection]):
"""
`wizard gen-import` 向导流程。
:param default_env: 默认环境
:param default_table_names: 默认物理表名称列表文本
:param default_dry_run: 默认是否先执行 dry-run
"""
wizard_name = 'wizard gen-import'
preview_title = 'wizard gen-import preview'
failure_message = '代码生成导入向导执行失败'
def __init__(
self,
*,
default_env: str = 'dev',
default_table_names: str = '',
default_dry_run: bool = True,
) -> None:
"""
初始化代码生成导入向导流程。
:param default_env: 默认环境
:param default_table_names: 默认物理表名称列表文本
:param default_dry_run: 默认是否先执行 dry-run
:return: None
"""
self.default_env = default_env
self.default_table_names = default_table_names
self.default_dry_run = default_dry_run
def collect_selection(self) -> GenImportWizardSelection:
"""
采集代码生成导入向导参数。
:return: 向导采集结果
"""
env = self.prompt_service.prompt_env(self.default_env)
raw_table_names = self.prompt_service.prompt_required_text(
'物理表名称列表(多个表请使用逗号分隔)',
self.default_table_names,
)
table_names = self.parse_table_names(raw_table_names)
while not table_names:
typer.echo('至少需要输入一个物理表名称,请重新输入。')
raw_table_names = self.prompt_service.prompt_required_text(
'物理表名称列表(多个表请使用逗号分隔)',
self.default_table_names,
)
table_names = self.parse_table_names(raw_table_names)
dry_run = self.prompt_service.prompt_confirm('是否先执行 dry-run 预演', default_value=self.default_dry_run)
allow_prod = (
self.prompt_service.prompt_confirm('当前为 prod 环境,是否允许继续执行', default_value=False)
if env == 'prod'
else False
)
return GenImportWizardSelection(
env=env,
table_names=table_names,
dry_run=dry_run,
allow_prod=allow_prod,
)
def prepare_context(self, selection: GenImportWizardSelection, output: OutputOption) -> CliContext:
"""
构建代码生成导入向导上下文。
:param selection: 向导采集结果
:param output: 输出格式
:return: CLI 上下文
"""
return self.build_regular_context(
selection.env,
output,
allow_prod=selection.allow_prod,
yes=True,
dry_run=selection.dry_run,
)
def build_preview_summary(self, selection: GenImportWizardSelection) -> dict[str, str]:
"""
构建代码生成导入预览摘要。
:param selection: 向导采集结果
:return: 预览摘要
"""
return {
'env': selection.env,
'table_names': ','.join(selection.table_names),
'dry_run': str(selection.dry_run).lower(),
'allow_prod': str(selection.allow_prod).lower(),
}
def build_preview_command(self, selection: GenImportWizardSelection) -> list[str]:
"""
构建代码生成导入预览命令。
:param selection: 向导采集结果
:return: 用户视角命令参数
"""
command = ['shierfeng', 'gen', 'import-table', *selection.table_names, f'--env={selection.env}']
if selection.dry_run:
command.append('--dry-run')
if selection.allow_prod:
command.append('--allow-prod')
return command
def build_preview_notes(self, selection: GenImportWizardSelection) -> list[str] | None:
"""
构建代码生成导入预览附加说明。
:param selection: 向导采集结果
:return: 预览附加说明
"""
del selection
return ['建议先确认物理表注释和字段规模,再决定是否执行真实导入。']
def confirm_prompt(self, selection: GenImportWizardSelection) -> str:
"""
返回代码生成导入最终确认提示。
:param selection: 向导采集结果
:return: 确认提示
"""
del selection
return '确认执行代码生成导入向导吗'
def build_execute_arguments(self, selection: GenImportWizardSelection, output: OutputOption) -> list[str]:
"""
构建代码生成导入内部 CLI 参数。
:param selection: 向导采集结果
:param output: 输出格式
:return: 内部 CLI 参数
"""
arguments = [
'gen',
'import-table',
*selection.table_names,
f'--env={selection.env}',
f'--output={output}',
'--yes',
]
if selection.dry_run:
arguments.append('--dry-run')
if selection.allow_prod:
arguments.append('--allow-prod')
return arguments
@staticmethod
def parse_table_names(raw_value: str) -> list[str]:
"""
将逗号分隔的物理表名称文本解析为列表。
:param raw_value: 原始输入文本
:return: 去空白后的物理表名称列表
"""
return [table_name.strip() for table_name in raw_value.split(',') if table_name.strip()]
def run_gen_import_wizard(
output: OutputOption = 'text',
*,
default_env: str = 'dev',
default_table_names: str = '',
default_dry_run: bool = True,
) -> None:
"""
执行 `wizard gen-import` 向导。
:param output: 输出格式
:param default_env: 默认环境
:param default_table_names: 默认物理表名称列表文本
:param default_dry_run: 默认是否先 dry-run
:return: None
"""
GenImportWizardFlow(
default_env=default_env,
default_table_names=default_table_names,
default_dry_run=default_dry_run,
).run(output)
@@ -0,0 +1,224 @@
from dataclasses import dataclass
from typing import Any
from cli.context import CliContext, OutputOption
from cli.wizard.aggregators import ProdCheckAggregator
from cli.wizard.base import BaseCliWizardFlow
from cli.wizard.presenters import ProdCheckPresenter
@dataclass(frozen=True)
class ProdCheckWizardSelection:
"""
`wizard prod-check` 向导采集结果。
:param env: 运行环境
:param include_config: 是否附带配置快照
"""
env: str
include_config: bool
class ProdCheckWizardFlow(BaseCliWizardFlow[ProdCheckWizardSelection]):
"""
`wizard prod-check` 向导流程。
:param default_env: 默认环境
:param default_include_config: 默认是否附带配置快照
"""
wizard_name = 'wizard prod-check'
preview_title = 'wizard prod-check preview'
failure_message = '生产巡检向导执行失败'
def __init__(
self,
*,
default_env: str = 'prod',
default_include_config: bool = True,
) -> None:
"""
初始化生产巡检向导流程。
:param default_env: 默认环境
:param default_include_config: 默认是否附带配置快照
:return: None
"""
super().__init__()
self.default_env = default_env
self.default_include_config = default_include_config
self.aggregator = ProdCheckAggregator()
self.presenter = ProdCheckPresenter()
def collect_selection(self) -> ProdCheckWizardSelection:
"""
采集生产巡检向导参数。
:return: 向导采集结果
"""
env = self.prompt_service.prompt_env(self.default_env)
include_config = self.prompt_service.prompt_confirm(
'是否附带应用配置快照',
default_value=self.default_include_config,
)
return ProdCheckWizardSelection(env=env, include_config=include_config)
def prepare_context(self, selection: ProdCheckWizardSelection, output: OutputOption) -> CliContext:
"""
构建生产巡检向导上下文。
:param selection: 向导采集结果
:param output: 输出格式
:return: CLI 上下文
"""
return self.build_readonly_context(selection.env, output)
def build_preview_summary(self, selection: ProdCheckWizardSelection) -> dict[str, str]:
"""
构建生产巡检预览摘要。
:param selection: 向导采集结果
:return: 预览摘要
"""
return {
'env': selection.env,
'include_config': str(selection.include_config).lower(),
}
def build_preview_command(self, selection: ProdCheckWizardSelection) -> list[str]:
"""
构建生产巡检预览命令。
:param selection: 向导采集结果
:return: 用户视角命令参数
"""
return ['shierfeng', 'app', 'doctor', f'--env={selection.env}']
def confirm_prompt(self, selection: ProdCheckWizardSelection) -> str:
"""
返回生产巡检最终确认提示。
:param selection: 向导采集结果
:return: 确认提示
"""
del selection
return '确认执行生产巡检向导吗'
def confirm_default_value(self, selection: ProdCheckWizardSelection) -> bool:
"""
返回生产巡检确认默认值。
:param selection: 向导采集结果
:return: 默认确认值
"""
del selection
return True
def build_execute_arguments(self, selection: ProdCheckWizardSelection, output: OutputOption) -> list[str]:
"""
返回生产巡检占位执行参数。
:param selection: 向导采集结果
:param output: 输出格式
:return: 内部 CLI 参数
"""
del selection, output
return []
def execute(self, selection: ProdCheckWizardSelection, output: OutputOption) -> dict[str, Any]:
"""
执行生产巡检聚合逻辑。
:param selection: 向导采集结果
:param output: 输出格式
:return: 聚合后的巡检结果
"""
del output
runtime_result = self.run_nested_command(
'app', 'env', f'--env={selection.env}', '--output=json', parse_json=True
)
doctor_result = self.run_nested_command(
'app',
'doctor',
f'--env={selection.env}',
'--output=json',
parse_json=True,
)
config_payload = None
if selection.include_config:
config_result = self.run_nested_command(
'app',
'config',
f'--env={selection.env}',
'--output=json',
parse_json=True,
)
config_payload = config_result.payload
return self.aggregator.build_payload(
env=selection.env,
runtime_payload=runtime_result.payload if isinstance(runtime_result.payload, dict) else None,
doctor_payload=doctor_result.payload if isinstance(doctor_result.payload, dict) else None,
config_payload=config_payload,
)
def complete_payload(
self,
ctx: CliContext,
payload: dict[str, Any],
*,
default_exit_code: int = 0,
) -> None:
"""
以聚合结果展示器收口生产巡检结果。
:param ctx: CLI 上下文
:param payload: 聚合结果负载
:param default_exit_code: 默认退出码
:return: None
"""
self.complete_payload_result(
ctx,
payload,
text_builder=self.presenter.build_text,
default_exit_code=default_exit_code,
)
def extract_payload(self, nested_result: Any) -> dict[str, Any] | None:
"""
提取生产巡检聚合结果负载。
:param nested_result: 聚合执行结果
:return: 结构化结果负载
"""
return nested_result if isinstance(nested_result, dict) else None
def extract_returncode(self, nested_result: Any) -> int:
"""
提取生产巡检聚合结果退出码。
:param nested_result: 聚合执行结果
:return: 退出码
"""
del nested_result
return 0
def run_prod_check_wizard(
output: OutputOption = 'text',
*,
default_env: str = 'prod',
default_include_config: bool = True,
) -> None:
"""
执行 `wizard prod-check` 向导。
:param output: 输出格式
:param default_env: 默认环境
:param default_include_config: 默认是否附带配置快照
:return: None
"""
ProdCheckWizardFlow(
default_env=default_env,
default_include_config=default_include_config,
).run(output)