AIDeveloper-PC/requirements_generator/ui/prompts.py

493 lines
18 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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
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
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
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