AIDeveloper-PC/requirements_generator/ui/prompts.py

493 lines
18 KiB
Python
Raw Permalink Normal View History

# ui/prompts.py - 交互式输入 / 选择工具函数
from typing import List, Optional
from rich.console import Console
from rich.prompt import Confirm, Prompt
import config
from database.db_manager import DBManager
from database.models import FunctionalRequirement, Project
from ui.display import print_projects_table
from utils.file_handler import merge_knowledge_files
console = Console()
db = DBManager()
def select_project(prompt_text: str = "请选择项目 ID") -> Optional[Project]:
"""展示项目列表,交互选择并返回 Project 对象;输入 0 返回 None。"""
projects = db.list_projects()
if not projects:
console.print("[yellow]当前暂无项目,请先新建项目。[/yellow]")
return None
print_projects_table(projects)
pid_str = Prompt.ask(f"{prompt_text}(输入 0 返回)", default="0")
if pid_str == "0":
return None
try:
pid = int(pid_str)
except ValueError:
console.print("[red]ID 必须为整数[/red]")
return None
2026-03-06 16:39:01 +00:00
project = db.get_project_by_id(pid)
if not project:
console.print(f"[red]项目 ID={pid} 不存在[/red]")
return None
return project
def load_knowledge_optional() -> str:
"""询问是否加载知识库文件,加载后返回合并文本;否则返回空字符串。"""
if Confirm.ask("是否加载知识库文件?", default=False):
kb_path = Prompt.ask("知识库文件路径(多个用逗号分隔)")
paths = [p.strip() for p in kb_path.split(",") if p.strip()]
text = merge_knowledge_files(paths)
console.print(f"[dim]已加载 {len(paths)} 个知识库文件[/dim]")
return text
return ""
def input_multiline(prompt_hint: str = "请输入内容") -> str:
"""多行文本输入,输入空行结束,返回合并字符串。"""
console.print(f"[dim]{prompt_hint}(输入空行结束):[/dim]")
lines: List[str] = []
while True:
line = input()
if line == "":
break
lines.append(line)
return "\n".join(lines).strip()
def pause() -> None:
"""暂停,等待用户按 Enter 键返回主菜单。"""
console.print()
input(" 按 Enter 键返回主菜单...")
def interactive_edit_req(
reqs: List[FunctionalRequirement],
) -> List[FunctionalRequirement]:
"""交互式编辑指定序号的需求字段。"""
idx_str = Prompt.ask("输入要编辑的序号")
try:
idx = int(idx_str)
except ValueError:
console.print("[red]序号必须为整数[/red]")
return reqs
for req in reqs:
if req.index_no == idx:
req.title = Prompt.ask("新标题", default=req.title)
req.description = Prompt.ask("新描述", default=req.description)
req.function_name = Prompt.ask("新函数名", default=req.function_name)
req.priority = Prompt.ask(
"新优先级", default=req.priority,
choices=["high", "medium", "low"],
)
req.module = Prompt.ask("新模块", default=req.module)
console.print(f"[green]✓ 序号 {idx} 已更新[/green]")
return reqs
console.print(f"[red]序号 {idx} 不存在[/red]")
return reqs
def interactive_delete_req(
reqs: List[FunctionalRequirement],
) -> List[FunctionalRequirement]:
"""交互式删除指定序号的需求(内存操作,未持久化)。"""
idx_str = Prompt.ask("输入要删除的序号")
try:
idx = int(idx_str)
except ValueError:
console.print("[red]序号必须为整数[/red]")
return reqs
new_reqs = [r for r in reqs if r.index_no != idx]
if len(new_reqs) < len(reqs):
console.print(f"[green]✓ 序号 {idx} 已删除[/green]")
else:
console.print(f"[red]序号 {idx} 不存在[/red]")
return new_reqs
def interactive_add_req(
reqs: List[FunctionalRequirement],
project: Project,
raw_req_id: int,
) -> List[FunctionalRequirement]:
"""交互式新增一条需求到列表(内存操作,未持久化)。"""
next_idx = max((r.index_no for r in reqs), default=0) + 1
title = Prompt.ask("新需求标题")
description = Prompt.ask("新需求描述")
function_name = Prompt.ask("函数名snake_case")
priority = Prompt.ask(
"优先级", choices=["high", "medium", "low"], default="medium",
)
module = Prompt.ask("所属模块", default=config.DEFAULT_MODULE)
new_req = FunctionalRequirement(
project_id = project.id,
raw_req_id = raw_req_id,
index_no = next_idx,
title = title,
description = description,
function_name = function_name,
priority = priority,
module = module,
status = "pending",
is_custom = True,
)
reqs.append(new_req)
console.print(f"[green]✓ 已添加新需求: {title}(序号 {next_idx}[/green]")
return reqs
def interactive_adjust_modules(
reqs: List[FunctionalRequirement],
) -> List[FunctionalRequirement]:
"""交互式逐条调整需求的模块归属,并立即持久化。"""
while True:
idx_str = Prompt.ask("输入要调整的需求序号(输入 0 结束)", default="0")
if idx_str == "0":
break
for req in reqs:
if str(req.index_no) == idx_str:
new_module = Prompt.ask(
f"'{req.function_name}' 新模块名", default=req.module,
)
req.module = new_module
db.update_functional_requirement(req)
console.print(
f"[green]✓ 已更新模块: {req.function_name}{new_module}[/green]"
)
break
else:
console.print(f"[red]序号 {idx_str} 不存在[/red]")
return reqs# ui/prompts.py - 交互式输入 / 选择工具函数
from typing import List, Optional
from rich.console import Console
from rich.prompt import Confirm, Prompt
import config
from database.db_manager import DBManager
from database.models import FunctionalRequirement, Project
from ui.display import print_projects_table
from utils.file_handler import merge_knowledge_files
console = Console()
db = DBManager()
def select_project(prompt_text: str = "请选择项目 ID") -> Optional[Project]:
"""展示项目列表,交互选择并返回 Project 对象;输入 0 返回 None。"""
projects = db.list_projects()
if not projects:
console.print("[yellow]当前暂无项目,请先新建项目。[/yellow]")
return None
print_projects_table(projects)
pid_str = Prompt.ask(f"{prompt_text}(输入 0 返回)", default="0")
if pid_str == "0":
return None
try:
pid = int(pid_str)
except ValueError:
console.print("[red]ID 必须为整数[/red]")
return None
2026-03-06 16:40:13 +00:00
project = db.get_project_by_id(pid)
if not project:
console.print(f"[red]项目 ID={pid} 不存在[/red]")
return None
return project
def load_knowledge_optional() -> str:
"""询问是否加载知识库文件,加载后返回合并文本;否则返回空字符串。"""
if Confirm.ask("是否加载知识库文件?", default=False):
kb_path = Prompt.ask("知识库文件路径(多个用逗号分隔)")
paths = [p.strip() for p in kb_path.split(",") if p.strip()]
text = merge_knowledge_files(paths)
console.print(f"[dim]已加载 {len(paths)} 个知识库文件[/dim]")
return text
return ""
def input_multiline(prompt_hint: str = "请输入内容") -> str:
"""多行文本输入,输入空行结束,返回合并字符串。"""
console.print(f"[dim]{prompt_hint}(输入空行结束):[/dim]")
lines: List[str] = []
while True:
line = input()
if line == "":
break
lines.append(line)
return "\n".join(lines).strip()
def pause() -> None:
"""暂停,等待用户按 Enter 键返回主菜单。"""
console.print()
input(" 按 Enter 键返回主菜单...")
def interactive_edit_req(
reqs: List[FunctionalRequirement],
) -> List[FunctionalRequirement]:
"""交互式编辑指定序号的需求字段。"""
idx_str = Prompt.ask("输入要编辑的序号")
try:
idx = int(idx_str)
except ValueError:
console.print("[red]序号必须为整数[/red]")
return reqs
for req in reqs:
if req.index_no == idx:
req.title = Prompt.ask("新标题", default=req.title)
req.description = Prompt.ask("新描述", default=req.description)
req.function_name = Prompt.ask("新函数名", default=req.function_name)
req.priority = Prompt.ask(
"新优先级", default=req.priority,
choices=["high", "medium", "low"],
)
req.module = Prompt.ask("新模块", default=req.module)
console.print(f"[green]✓ 序号 {idx} 已更新[/green]")
return reqs
console.print(f"[red]序号 {idx} 不存在[/red]")
return reqs
def interactive_delete_req(
reqs: List[FunctionalRequirement],
) -> List[FunctionalRequirement]:
"""交互式删除指定序号的需求(内存操作,未持久化)。"""
idx_str = Prompt.ask("输入要删除的序号")
try:
idx = int(idx_str)
except ValueError:
console.print("[red]序号必须为整数[/red]")
return reqs
new_reqs = [r for r in reqs if r.index_no != idx]
if len(new_reqs) < len(reqs):
console.print(f"[green]✓ 序号 {idx} 已删除[/green]")
else:
console.print(f"[red]序号 {idx} 不存在[/red]")
return new_reqs
def interactive_add_req(
reqs: List[FunctionalRequirement],
project: Project,
raw_req_id: int,
) -> List[FunctionalRequirement]:
"""交互式新增一条需求到列表(内存操作,未持久化)。"""
next_idx = max((r.index_no for r in reqs), default=0) + 1
title = Prompt.ask("新需求标题")
description = Prompt.ask("新需求描述")
function_name = Prompt.ask("函数名snake_case")
priority = Prompt.ask(
"优先级", choices=["high", "medium", "low"], default="medium",
)
module = Prompt.ask("所属模块", default=config.DEFAULT_MODULE)
new_req = FunctionalRequirement(
project_id = project.id,
raw_req_id = raw_req_id,
index_no = next_idx,
title = title,
description = description,
function_name = function_name,
priority = priority,
module = module,
status = "pending",
is_custom = True,
)
reqs.append(new_req)
console.print(f"[green]✓ 已添加新需求: {title}(序号 {next_idx}[/green]")
return reqs
def interactive_adjust_modules(
reqs: List[FunctionalRequirement],
) -> List[FunctionalRequirement]:
"""交互式逐条调整需求的模块归属,并立即持久化。"""
while True:
idx_str = Prompt.ask("输入要调整的需求序号(输入 0 结束)", default="0")
if idx_str == "0":
break
for req in reqs:
if str(req.index_no) == idx_str:
new_module = Prompt.ask(
f"'{req.function_name}' 新模块名", default=req.module,
)
req.module = new_module
db.update_functional_requirement(req)
console.print(
f"[green]✓ 已更新模块: {req.function_name}{new_module}[/green]"
)
break
else:
console.print(f"[red]序号 {idx_str} 不存在[/red]")
return reqs# ui/prompts.py - 交互式输入 / 选择工具函数
from typing import List, Optional
from rich.console import Console
from rich.prompt import Confirm, Prompt
import config
from database.db_manager import DBManager
from database.models import FunctionalRequirement, Project
from ui.display import print_projects_table
from utils.file_handler import merge_knowledge_files
console = Console()
db = DBManager()
def select_project(prompt_text: str = "请选择项目 ID") -> Optional[Project]:
"""展示项目列表,交互选择并返回 Project 对象;输入 0 返回 None。"""
projects = db.list_projects()
if not projects:
console.print("[yellow]当前暂无项目,请先新建项目。[/yellow]")
return None
print_projects_table(projects)
pid_str = Prompt.ask(f"{prompt_text}(输入 0 返回)", default="0")
if pid_str == "0":
return None
try:
pid = int(pid_str)
except ValueError:
console.print("[red]ID 必须为整数[/red]")
return None
2026-03-06 16:40:13 +00:00
project = db.get_project_by_id(pid)
if not project:
console.print(f"[red]项目 ID={pid} 不存在[/red]")
return None
return project
def load_knowledge_optional() -> str:
"""询问是否加载知识库文件,加载后返回合并文本;否则返回空字符串。"""
if Confirm.ask("是否加载知识库文件?", default=False):
kb_path = Prompt.ask("知识库文件路径(多个用逗号分隔)")
paths = [p.strip() for p in kb_path.split(",") if p.strip()]
text = merge_knowledge_files(paths)
console.print(f"[dim]已加载 {len(paths)} 个知识库文件[/dim]")
return text
return ""
def input_multiline(prompt_hint: str = "请输入内容") -> str:
"""多行文本输入,输入空行结束,返回合并字符串。"""
console.print(f"[dim]{prompt_hint}(输入空行结束):[/dim]")
lines: List[str] = []
while True:
line = input()
if line == "":
break
lines.append(line)
return "\n".join(lines).strip()
def pause() -> None:
"""暂停,等待用户按 Enter 键返回主菜单。"""
console.print()
input(" 按 Enter 键返回主菜单...")
def interactive_edit_req(
reqs: List[FunctionalRequirement],
) -> List[FunctionalRequirement]:
"""交互式编辑指定序号的需求字段。"""
idx_str = Prompt.ask("输入要编辑的序号")
try:
idx = int(idx_str)
except ValueError:
console.print("[red]序号必须为整数[/red]")
return reqs
for req in reqs:
if req.index_no == idx:
req.title = Prompt.ask("新标题", default=req.title)
req.description = Prompt.ask("新描述", default=req.description)
req.function_name = Prompt.ask("新函数名", default=req.function_name)
req.priority = Prompt.ask(
"新优先级", default=req.priority,
choices=["high", "medium", "low"],
)
req.module = Prompt.ask("新模块", default=req.module)
console.print(f"[green]✓ 序号 {idx} 已更新[/green]")
return reqs
console.print(f"[red]序号 {idx} 不存在[/red]")
return reqs
def interactive_delete_req(
reqs: List[FunctionalRequirement],
) -> List[FunctionalRequirement]:
"""交互式删除指定序号的需求(内存操作,未持久化)。"""
idx_str = Prompt.ask("输入要删除的序号")
try:
idx = int(idx_str)
except ValueError:
console.print("[red]序号必须为整数[/red]")
return reqs
new_reqs = [r for r in reqs if r.index_no != idx]
if len(new_reqs) < len(reqs):
console.print(f"[green]✓ 序号 {idx} 已删除[/green]")
else:
console.print(f"[red]序号 {idx} 不存在[/red]")
return new_reqs
def interactive_add_req(
reqs: List[FunctionalRequirement],
project: Project,
raw_req_id: int,
) -> List[FunctionalRequirement]:
"""交互式新增一条需求到列表(内存操作,未持久化)。"""
next_idx = max((r.index_no for r in reqs), default=0) + 1
title = Prompt.ask("新需求标题")
description = Prompt.ask("新需求描述")
function_name = Prompt.ask("函数名snake_case")
priority = Prompt.ask(
"优先级", choices=["high", "medium", "low"], default="medium",
)
module = Prompt.ask("所属模块", default=config.DEFAULT_MODULE)
new_req = FunctionalRequirement(
project_id = project.id,
raw_req_id = raw_req_id,
index_no = next_idx,
title = title,
description = description,
function_name = function_name,
priority = priority,
module = module,
status = "pending",
is_custom = True,
)
reqs.append(new_req)
console.print(f"[green]✓ 已添加新需求: {title}(序号 {next_idx}[/green]")
return reqs
def interactive_adjust_modules(
reqs: List[FunctionalRequirement],
) -> List[FunctionalRequirement]:
"""交互式逐条调整需求的模块归属,并立即持久化。"""
while True:
idx_str = Prompt.ask("输入要调整的需求序号(输入 0 结束)", default="0")
if idx_str == "0":
break
for req in reqs:
if str(req.index_no) == idx_str:
new_module = Prompt.ask(
f"'{req.function_name}' 新模块名", default=req.module,
)
req.module = new_module
db.update_functional_requirement(req)
console.print(
f"[green]✓ 已更新模块: {req.function_name}{new_module}[/green]"
)
break
else:
console.print(f"[red]序号 {idx_str} 不存在[/red]")
return reqs