Skip to main content

aster/blueprint/
requirement_dialog.rs

1//! 需求对话流程管理器
2//!
3//! 实现 ERP 式的对话式需求收集,通过多步骤对话引导用户完善项目需求:
4//! 1. 项目背景 - 目标用户、要解决的问题
5//! 2. 核心流程 - 主要业务流程
6//! 3. 系统模块 - 功能模块划分
7//! 4. 非功能要求 - 性能、安全、可用性
8//! 5. 确认汇总 - 生成蓝图草案供用户确认
9
10use chrono::{DateTime, Utc};
11use std::collections::HashMap;
12use tokio::sync::mpsc;
13
14use super::blueprint_manager::BlueprintManager;
15use super::types::{
16    Blueprint, BusinessProcess, ModuleType, MoscowPriority, NfrCategory, NonFunctionalRequirement,
17    ProcessStep, ProcessType, SystemModule,
18};
19
20// ============================================================================
21// 类型定义
22// ============================================================================
23
24/// 对话阶段
25#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
26pub enum DialogPhase {
27    #[default]
28    Welcome,
29    ProjectBackground,
30    BusinessProcess,
31    SystemModule,
32    NFR,
33    Summary,
34    Complete,
35}
36
37/// 对话状态
38#[derive(Debug, Clone)]
39pub struct DialogState {
40    pub id: String,
41    pub phase: DialogPhase,
42    pub project_name: String,
43    pub project_description: String,
44    pub target_users: Vec<String>,
45    pub problems_to_solve: Vec<String>,
46    pub business_processes: Vec<BusinessProcessDraft>,
47    pub modules: Vec<SystemModuleDraft>,
48    pub nfrs: Vec<NFRDraft>,
49    pub history: Vec<DialogMessage>,
50    pub created_at: DateTime<Utc>,
51    pub updated_at: DateTime<Utc>,
52}
53
54impl Default for DialogState {
55    fn default() -> Self {
56        Self {
57            id: uuid::Uuid::new_v4().to_string(),
58            phase: DialogPhase::Welcome,
59            project_name: String::new(),
60            project_description: String::new(),
61            target_users: vec![],
62            problems_to_solve: vec![],
63            business_processes: vec![],
64            modules: vec![],
65            nfrs: vec![],
66            history: vec![],
67            created_at: Utc::now(),
68            updated_at: Utc::now(),
69        }
70    }
71}
72
73/// 对话消息
74#[derive(Debug, Clone)]
75pub struct DialogMessage {
76    pub id: String,
77    pub role: MessageRole,
78    pub content: String,
79    pub timestamp: DateTime<Utc>,
80    pub phase: DialogPhase,
81}
82
83/// 消息角色
84#[derive(Debug, Clone, Copy, PartialEq, Eq)]
85pub enum MessageRole {
86    Assistant,
87    User,
88}
89
90/// 业务流程草稿
91#[derive(Debug, Clone)]
92pub struct BusinessProcessDraft {
93    pub name: String,
94    pub description: String,
95    pub process_type: ProcessDraftType,
96    pub steps: Vec<String>,
97}
98
99/// 流程草稿类型
100#[derive(Debug, Clone, Copy, PartialEq, Eq)]
101pub enum ProcessDraftType {
102    Core,
103    Support,
104    Management,
105}
106
107/// 系统模块草稿
108#[derive(Debug, Clone)]
109pub struct SystemModuleDraft {
110    pub name: String,
111    pub description: String,
112    pub module_type: ModuleDraftType,
113    pub responsibilities: Vec<String>,
114    pub tech_stack: Vec<String>,
115    pub dependencies: Vec<String>,
116}
117
118/// 模块草稿类型
119#[derive(Debug, Clone, Copy, PartialEq, Eq)]
120pub enum ModuleDraftType {
121    Frontend,
122    Backend,
123    Database,
124    Service,
125    Infrastructure,
126}
127
128impl From<ModuleDraftType> for ModuleType {
129    fn from(t: ModuleDraftType) -> Self {
130        match t {
131            ModuleDraftType::Frontend => ModuleType::Frontend,
132            ModuleDraftType::Backend => ModuleType::Backend,
133            ModuleDraftType::Database => ModuleType::Database,
134            ModuleDraftType::Service => ModuleType::Service,
135            ModuleDraftType::Infrastructure => ModuleType::Infrastructure,
136        }
137    }
138}
139
140/// 非功能要求草稿
141#[derive(Debug, Clone)]
142pub struct NFRDraft {
143    pub category: NFRDraftCategory,
144    pub name: String,
145    pub description: String,
146    pub priority: NFRDraftPriority,
147    pub metrics: Option<String>,
148}
149
150/// NFR 草稿类别
151#[derive(Debug, Clone, Copy, PartialEq, Eq)]
152pub enum NFRDraftCategory {
153    Performance,
154    Security,
155    Availability,
156    Scalability,
157    Usability,
158    Maintainability,
159    Other,
160}
161
162impl From<NFRDraftCategory> for NfrCategory {
163    fn from(c: NFRDraftCategory) -> Self {
164        match c {
165            NFRDraftCategory::Performance => NfrCategory::Performance,
166            NFRDraftCategory::Security => NfrCategory::Security,
167            NFRDraftCategory::Availability => NfrCategory::Availability,
168            NFRDraftCategory::Scalability => NfrCategory::Scalability,
169            NFRDraftCategory::Usability => NfrCategory::Usability,
170            NFRDraftCategory::Maintainability => NfrCategory::Maintainability,
171            NFRDraftCategory::Other => NfrCategory::Other,
172        }
173    }
174}
175
176/// NFR 草稿优先级
177#[derive(Debug, Clone, Copy, PartialEq, Eq)]
178pub enum NFRDraftPriority {
179    Must,
180    Should,
181    Could,
182}
183
184impl From<NFRDraftPriority> for MoscowPriority {
185    fn from(p: NFRDraftPriority) -> Self {
186        match p {
187            NFRDraftPriority::Must => MoscowPriority::Must,
188            NFRDraftPriority::Should => MoscowPriority::Should,
189            NFRDraftPriority::Could => MoscowPriority::Could,
190        }
191    }
192}
193
194/// 对话事件
195#[derive(Debug, Clone)]
196pub enum DialogEvent {
197    Started {
198        session_id: String,
199    },
200    Message {
201        session_id: String,
202        message: DialogMessage,
203    },
204    PhaseChanged {
205        session_id: String,
206        phase: DialogPhase,
207    },
208    Ended {
209        session_id: String,
210    },
211}
212
213// ============================================================================
214// 对话提示词
215// ============================================================================
216
217/// 获取阶段提示词
218fn get_phase_prompt(phase: DialogPhase) -> &'static str {
219    match phase {
220        DialogPhase::Welcome => {
221            r#"你好!我是你的项目需求分析助手。
222
223在开始构建项目蓝图之前,我需要了解一些关于你项目的信息。这个过程分为几个步骤:
224
2251. **项目背景** - 了解你的目标用户和要解决的问题
2262. **核心流程** - 梳理主要的业务流程
2273. **系统模块** - 确定需要的功能模块
2284. **非功能要求** - 讨论性能、安全等要求
2295. **确认汇总** - 生成蓝图草案供你确认
230
231让我们开始吧!首先,请告诉我:
232
233**你的项目叫什么名字?想要解决什么问题?**"#
234        }
235
236        DialogPhase::ProjectBackground => {
237            r#"很好!现在让我更深入地了解你的项目背景。
238
239请回答以下问题:
240
2411. **目标用户是谁?** (例如:企业员工、普通消费者、开发者...)
2422. **他们目前面临什么痛点?**
2433. **你的解决方案有什么独特之处?**
2444. **项目的预期规模是怎样的?** (用户量、数据量等)
245
246你可以一次回答所有问题,也可以逐个回答。"#
247        }
248
249        DialogPhase::BusinessProcess => {
250            r#"太棒了!现在让我们来梳理业务流程。
251
252一个好的业务流程设计能帮助我们更清晰地理解系统需求。请思考:
253
2541. **核心业务流程** - 用户完成主要任务的步骤
2552. **支撑流程** - 支持核心业务的辅助流程
2563. **管理流程** - 后台管理相关的流程
257
258请描述你项目的主要业务流程,包括:
259- 流程名称
260- 流程类型(核心/支撑/管理)
261- 主要步骤"#
262        }
263
264        DialogPhase::SystemModule => {
265            r#"非常好!现在让我们来划分系统模块。
266
267每个模块需要包含:
268- 模块名称
269- 模块类型(前端/后端/数据库/服务/基础设施)
270- 主要职责
271- 技术栈建议
272- 依赖关系
273
274请告诉我:
2751. 你认为需要哪些模块?
2762. 你对技术栈有什么偏好?"#
277        }
278
279        DialogPhase::NFR => {
280            r#"模块设计很清晰!现在让我们讨论非功能性要求。
281
282非功能性要求包括:
283
2841. **性能** - 响应时间、吞吐量、并发数
2852. **安全** - 认证、授权、数据加密
2863. **可用性** - 系统可用时间、故障恢复
2874. **可扩展性** - 水平扩展、垂直扩展
2885. **可维护性** - 代码质量、文档、监控
289
290请告诉我你对这些方面的要求。"#
291        }
292
293        DialogPhase::Summary => {
294            r#"太棒了!我已经收集了所有需求信息。
295
296请仔细检查并确认蓝图草案。
297
298你可以:
2991. **确认** - 蓝图没问题,可以进入下一步
3002. **修改** - 告诉我需要修改的内容
3013. **重来** - 重新开始需求收集
302
303请输入"确认"、"修改 [内容]"或"重来"。"#
304        }
305
306        DialogPhase::Complete => {
307            r#"蓝图已创建完成!
308
309你可以:
3101. 查看完整蓝图
3112. 提交审核
3123. 确认签字后开始执行
313
314祝你的项目顺利!"#
315        }
316    }
317}
318
319// ============================================================================
320// 需求对话管理器
321// ============================================================================
322
323/// 需求对话管理器
324pub struct RequirementDialogManager {
325    sessions: HashMap<String, DialogState>,
326    event_sender: Option<mpsc::Sender<DialogEvent>>,
327}
328
329impl Default for RequirementDialogManager {
330    fn default() -> Self {
331        Self::new()
332    }
333}
334
335impl RequirementDialogManager {
336    /// 创建新的管理器
337    pub fn new() -> Self {
338        Self {
339            sessions: HashMap::new(),
340            event_sender: None,
341        }
342    }
343
344    /// 设置事件发送器
345    #[allow(dead_code)]
346    pub fn with_event_sender(mut self, sender: mpsc::Sender<DialogEvent>) -> Self {
347        self.event_sender = Some(sender);
348        self
349    }
350
351    /// 发送事件
352    async fn emit(&self, event: DialogEvent) {
353        if let Some(ref sender) = self.event_sender {
354            let _ = sender.send(event).await;
355        }
356    }
357
358    /// 开始新的对话
359    pub async fn start_dialog(&mut self) -> DialogState {
360        let mut state = DialogState::default();
361
362        // 添加欢迎消息
363        state.history.push(DialogMessage {
364            id: uuid::Uuid::new_v4().to_string(),
365            role: MessageRole::Assistant,
366            content: get_phase_prompt(DialogPhase::Welcome).to_string(),
367            timestamp: Utc::now(),
368            phase: DialogPhase::Welcome,
369        });
370
371        self.sessions.insert(state.id.clone(), state.clone());
372        self.emit(DialogEvent::Started {
373            session_id: state.id.clone(),
374        })
375        .await;
376
377        state
378    }
379
380    /// 处理用户输入
381    pub async fn process_user_input(
382        &mut self,
383        session_id: &str,
384        input: &str,
385    ) -> Result<DialogMessage, String> {
386        // 先获取状态的副本和当前阶段
387        let (current_phase, mut state_clone) = {
388            let state = self
389                .sessions
390                .get(session_id)
391                .ok_or_else(|| format!("对话会话 {} 不存在", session_id))?;
392            (state.phase, state.clone())
393        };
394
395        // 记录用户消息
396        let user_message = DialogMessage {
397            id: uuid::Uuid::new_v4().to_string(),
398            role: MessageRole::User,
399            content: input.to_string(),
400            timestamp: Utc::now(),
401            phase: current_phase,
402        };
403        state_clone.history.push(user_message.clone());
404        state_clone.updated_at = Utc::now();
405
406        // 根据当前阶段处理输入(使用静态方法避免借用冲突)
407        let (response, next_phase) = match current_phase {
408            DialogPhase::Welcome => {
409                Self::process_welcome_input_static(&mut state_clone, input);
410                (
411                    Self::format_welcome_response_static(&state_clone),
412                    DialogPhase::ProjectBackground,
413                )
414            }
415            DialogPhase::ProjectBackground => {
416                Self::process_background_input_static(&mut state_clone, input);
417                (
418                    Self::format_background_response_static(&state_clone),
419                    DialogPhase::BusinessProcess,
420                )
421            }
422            DialogPhase::BusinessProcess => {
423                Self::process_business_process_input_static(&mut state_clone, input);
424                (
425                    Self::format_business_process_response_static(&state_clone),
426                    DialogPhase::SystemModule,
427                )
428            }
429            DialogPhase::SystemModule => {
430                Self::process_module_input_static(&mut state_clone, input);
431                (
432                    Self::format_module_response_static(&state_clone),
433                    DialogPhase::NFR,
434                )
435            }
436            DialogPhase::NFR => {
437                Self::process_nfr_input_static(&mut state_clone, input);
438                let summary = Self::generate_summary_static(&state_clone);
439                (
440                    format!("{}\n\n{}", summary, get_phase_prompt(DialogPhase::Summary)),
441                    DialogPhase::Summary,
442                )
443            }
444            DialogPhase::Summary => Self::process_summary_input_static(&mut state_clone, input),
445            DialogPhase::Complete => ("对话已完成。".to_string(), DialogPhase::Complete),
446        };
447
448        // 更新阶段
449        state_clone.phase = next_phase;
450
451        // 记录助手回复
452        let assistant_message = DialogMessage {
453            id: uuid::Uuid::new_v4().to_string(),
454            role: MessageRole::Assistant,
455            content: response,
456            timestamp: Utc::now(),
457            phase: state_clone.phase,
458        };
459        state_clone.history.push(assistant_message.clone());
460
461        // 更新会话状态
462        self.sessions.insert(session_id.to_string(), state_clone);
463
464        self.emit(DialogEvent::Message {
465            session_id: session_id.to_string(),
466            message: assistant_message.clone(),
467        })
468        .await;
469
470        Ok(assistant_message)
471    }
472
473    /// 处理欢迎阶段输入(静态版本)
474    fn process_welcome_input_static(state: &mut DialogState, input: &str) {
475        let first_line = input.lines().next().unwrap_or(input);
476        state.project_name = first_line.chars().take(50).collect();
477        state.project_description = input.to_string();
478    }
479
480    /// 格式化欢迎响应(静态版本)
481    fn format_welcome_response_static(state: &DialogState) -> String {
482        format!(
483            "很好!我了解了:\n\n**项目名称**:{}\n**项目目标**:{}\n\n{}",
484            state.project_name,
485            state
486                .project_description
487                .chars()
488                .take(200)
489                .collect::<String>(),
490            get_phase_prompt(DialogPhase::ProjectBackground)
491        )
492    }
493
494    /// 处理项目背景阶段输入(静态版本)
495    fn process_background_input_static(state: &mut DialogState, input: &str) {
496        for line in input.lines() {
497            let line_lower = line.to_lowercase();
498            if line_lower.contains("用户") || line_lower.contains("user") {
499                state.target_users.push(line.to_string());
500            }
501            if line_lower.contains("问题") || line_lower.contains("痛点") {
502                state.problems_to_solve.push(line.to_string());
503            }
504        }
505        if state.target_users.is_empty() && state.problems_to_solve.is_empty() {
506            state.project_description.push('\n');
507            state.project_description.push_str(input);
508        }
509    }
510
511    /// 格式化背景响应(静态版本)
512    fn format_background_response_static(state: &DialogState) -> String {
513        format!(
514            "太棒了!我已经记录了这些背景信息:\n\n**目标用户**:{}\n**要解决的问题**:\n{}\n\n{}",
515            if state.target_users.is_empty() {
516                "待确定".to_string()
517            } else {
518                state.target_users.join("、")
519            },
520            if state.problems_to_solve.is_empty() {
521                "- 待确定".to_string()
522            } else {
523                state
524                    .problems_to_solve
525                    .iter()
526                    .map(|p| format!("- {}", p))
527                    .collect::<Vec<_>>()
528                    .join("\n")
529            },
530            get_phase_prompt(DialogPhase::BusinessProcess)
531        )
532    }
533
534    /// 处理业务流程阶段输入(静态版本)
535    fn process_business_process_input_static(state: &mut DialogState, input: &str) {
536        let mut current_process: Option<BusinessProcessDraft> = None;
537
538        for line in input.lines() {
539            let line = line.trim();
540            if line.is_empty() {
541                continue;
542            }
543
544            let process_type = if line.contains("核心") {
545                Some(ProcessDraftType::Core)
546            } else if line.contains("支撑") {
547                Some(ProcessDraftType::Support)
548            } else if line.contains("管理") {
549                Some(ProcessDraftType::Management)
550            } else {
551                None
552            };
553
554            if let Some(pt) = process_type {
555                if let Some(p) = current_process.take() {
556                    state.business_processes.push(p);
557                }
558                current_process = Some(BusinessProcessDraft {
559                    name: line.to_string(),
560                    description: String::new(),
561                    process_type: pt,
562                    steps: vec![],
563                });
564            } else if let Some(ref mut p) = current_process {
565                if line.starts_with('-') || line.starts_with('•') || line.starts_with("步骤") {
566                    p.steps
567                        .push(line.trim_start_matches(['-', '•', ' ']).to_string());
568                } else {
569                    p.description.push_str(line);
570                    p.description.push(' ');
571                }
572            }
573        }
574
575        if let Some(p) = current_process {
576            state.business_processes.push(p);
577        }
578
579        if state.business_processes.is_empty() {
580            state.business_processes.push(BusinessProcessDraft {
581                name: "主要业务流程".to_string(),
582                description: input.to_string(),
583                process_type: ProcessDraftType::Core,
584                steps: input
585                    .lines()
586                    .filter(|l| !l.trim().is_empty())
587                    .map(|l| l.to_string())
588                    .collect(),
589            });
590        }
591    }
592
593    /// 格式化业务流程响应(静态版本)
594    fn format_business_process_response_static(state: &DialogState) -> String {
595        let processes_str = state
596            .business_processes
597            .iter()
598            .map(|p| {
599                format!(
600                    "- **{}** ({:?}): {} 个步骤",
601                    p.name,
602                    p.process_type,
603                    p.steps.len()
604                )
605            })
606            .collect::<Vec<_>>()
607            .join("\n");
608
609        format!(
610            "我已记录以下业务流程:\n\n{}\n\n{}",
611            processes_str,
612            get_phase_prompt(DialogPhase::SystemModule)
613        )
614    }
615
616    /// 处理模块阶段输入(静态版本)
617    fn process_module_input_static(state: &mut DialogState, input: &str) {
618        let mut current_module: Option<SystemModuleDraft> = None;
619
620        for line in input.lines() {
621            let line = line.trim();
622            if line.is_empty() {
623                continue;
624            }
625
626            let module_type = if line.contains("前端")
627                || line.contains("frontend")
628                || line.contains("UI")
629            {
630                Some(ModuleDraftType::Frontend)
631            } else if line.contains("后端") || line.contains("backend") || line.contains("API") {
632                Some(ModuleDraftType::Backend)
633            } else if line.contains("数据") || line.contains("database") || line.contains("存储")
634            {
635                Some(ModuleDraftType::Database)
636            } else if line.contains("服务") || line.contains("service") {
637                Some(ModuleDraftType::Service)
638            } else {
639                None
640            };
641
642            if let Some(mt) = module_type {
643                if let Some(m) = current_module.take() {
644                    state.modules.push(m);
645                }
646                current_module = Some(SystemModuleDraft {
647                    name: line.to_string(),
648                    description: String::new(),
649                    module_type: mt,
650                    responsibilities: vec![],
651                    tech_stack: vec![],
652                    dependencies: vec![],
653                });
654            } else if let Some(ref mut m) = current_module {
655                if line.starts_with('-') || line.starts_with('•') {
656                    m.responsibilities
657                        .push(line.trim_start_matches(['-', '•', ' ']).to_string());
658                } else {
659                    m.description.push_str(line);
660                    m.description.push(' ');
661                }
662            }
663        }
664
665        if let Some(m) = current_module {
666            state.modules.push(m);
667        }
668
669        if state.modules.is_empty() {
670            state.modules.push(SystemModuleDraft {
671                name: "主模块".to_string(),
672                description: input.to_string(),
673                module_type: ModuleDraftType::Backend,
674                responsibilities: input
675                    .lines()
676                    .filter(|l| !l.trim().is_empty())
677                    .map(|l| l.to_string())
678                    .collect(),
679                tech_stack: vec![],
680                dependencies: vec![],
681            });
682        }
683    }
684
685    /// 格式化模块响应(静态版本)
686    fn format_module_response_static(state: &DialogState) -> String {
687        let modules_str = state
688            .modules
689            .iter()
690            .map(|m| {
691                format!(
692                    "- **{}** ({:?}): {} 项职责",
693                    m.name,
694                    m.module_type,
695                    m.responsibilities.len()
696                )
697            })
698            .collect::<Vec<_>>()
699            .join("\n");
700
701        format!(
702            "我已记录以下系统模块:\n\n{}\n\n{}",
703            modules_str,
704            get_phase_prompt(DialogPhase::NFR)
705        )
706    }
707
708    /// 处理 NFR 阶段输入(静态版本)
709    fn process_nfr_input_static(state: &mut DialogState, input: &str) {
710        for line in input.lines() {
711            let line = line.trim();
712            if line.is_empty() {
713                continue;
714            }
715
716            let category = if line.contains("性能") || line.contains("performance") {
717                NFRDraftCategory::Performance
718            } else if line.contains("安全") || line.contains("security") {
719                NFRDraftCategory::Security
720            } else if line.contains("可用") || line.contains("availability") {
721                NFRDraftCategory::Availability
722            } else if line.contains("可维护") || line.contains("maintainability") {
723                NFRDraftCategory::Maintainability
724            } else {
725                NFRDraftCategory::Other
726            };
727
728            state.nfrs.push(NFRDraft {
729                name: line.to_string(),
730                description: line.to_string(),
731                category,
732                priority: NFRDraftPriority::Should,
733                metrics: None,
734            });
735        }
736
737        if state.nfrs.is_empty() {
738            state.nfrs.push(NFRDraft {
739                name: "基本可用性".to_string(),
740                description: "系统应保持基本可用".to_string(),
741                category: NFRDraftCategory::Availability,
742                priority: NFRDraftPriority::Must,
743                metrics: None,
744            });
745        }
746    }
747
748    /// 生成摘要(静态版本)
749    fn generate_summary_static(state: &DialogState) -> String {
750        let mut summary = String::new();
751        summary.push_str(&format!("# 蓝图摘要:{}\n\n", state.project_name));
752        summary.push_str(&format!("## 项目描述\n{}\n\n", state.project_description));
753
754        summary.push_str("## 业务流程\n");
755        for p in &state.business_processes {
756            summary.push_str(&format!("- **{}** ({:?})\n", p.name, p.process_type));
757            for step in &p.steps {
758                summary.push_str(&format!("  - {}\n", step));
759            }
760        }
761        summary.push('\n');
762
763        summary.push_str("## 系统模块\n");
764        for m in &state.modules {
765            summary.push_str(&format!("- **{}** ({:?})\n", m.name, m.module_type));
766            for r in &m.responsibilities {
767                summary.push_str(&format!("  - {}\n", r));
768            }
769        }
770        summary.push('\n');
771
772        summary.push_str("## 非功能性要求\n");
773        for n in &state.nfrs {
774            summary.push_str(&format!(
775                "- **{}** ({:?}, {:?})\n",
776                n.name, n.category, n.priority
777            ));
778        }
779
780        summary
781    }
782
783    /// 处理摘要阶段输入(静态版本)
784    fn process_summary_input_static(
785        _state: &mut DialogState,
786        input: &str,
787    ) -> (String, DialogPhase) {
788        let input_lower = input.to_lowercase();
789        if input_lower.contains("确认")
790            || input_lower.contains("ok")
791            || input_lower.contains("好")
792            || input_lower.contains("yes")
793        {
794            (
795                "太好了!蓝图已确认。现在可以生成正式蓝图了。".to_string(),
796                DialogPhase::Complete,
797            )
798        } else if input_lower.contains("修改") || input_lower.contains("改") {
799            (
800                "好的,请告诉我需要修改的内容。".to_string(),
801                DialogPhase::Summary,
802            )
803        } else {
804            (
805                "请确认蓝图内容是否正确,或告诉我需要修改的地方。".to_string(),
806                DialogPhase::Summary,
807            )
808        }
809    }
810
811    /// 处理欢迎阶段输入
812    #[allow(dead_code)]
813    fn process_welcome_input(&self, state: &mut DialogState, input: &str) {
814        Self::process_welcome_input_static(state, input);
815    }
816
817    /// 格式化欢迎响应
818    #[allow(dead_code)]
819    fn format_welcome_response(&self, state: &DialogState) -> String {
820        Self::format_welcome_response_static(state)
821    }
822
823    /// 处理项目背景阶段输入
824    #[allow(dead_code)]
825    fn process_background_input(&self, state: &mut DialogState, input: &str) {
826        Self::process_background_input_static(state, input);
827    }
828
829    /// 格式化背景响应
830    #[allow(dead_code)]
831    fn format_background_response(&self, state: &DialogState) -> String {
832        Self::format_background_response_static(state)
833    }
834
835    /// 处理业务流程阶段输入
836    #[allow(dead_code)]
837    fn process_business_process_input(&self, state: &mut DialogState, input: &str) {
838        Self::process_business_process_input_static(state, input);
839    }
840
841    /// 格式化业务流程响应
842    #[allow(dead_code)]
843    fn format_business_process_response(&self, state: &DialogState) -> String {
844        Self::format_business_process_response_static(state)
845    }
846
847    /// 处理系统模块阶段输入
848    #[allow(dead_code)]
849    fn process_module_input(&self, state: &mut DialogState, input: &str) {
850        // 如果还没有模块,先生成建议模块
851        if state.modules.is_empty() {
852            state.modules = self.suggest_modules(state);
853        }
854        Self::process_module_input_static(state, input);
855    }
856
857    /// 格式化模块响应
858    #[allow(dead_code)]
859    fn format_module_response(&self, state: &DialogState) -> String {
860        Self::format_module_response_static(state)
861    }
862
863    /// 建议系统模块
864    #[allow(dead_code)]
865    fn suggest_modules(&self, state: &DialogState) -> Vec<SystemModuleDraft> {
866        let mut modules = Vec::new();
867
868        // 根据业务流程推断需要的模块
869        let has_user_flow = state
870            .business_processes
871            .iter()
872            .any(|p| p.name.contains("用户") || p.name.contains("登录") || p.name.contains("注册"));
873
874        // 前端模块
875        modules.push(SystemModuleDraft {
876            name: "前端应用".to_string(),
877            description: "用户界面".to_string(),
878            module_type: ModuleDraftType::Frontend,
879            responsibilities: vec!["用户界面渲染".to_string(), "用户交互处理".to_string()],
880            tech_stack: vec!["React".to_string(), "TypeScript".to_string()],
881            dependencies: vec!["后端服务".to_string()],
882        });
883
884        // 后端模块
885        modules.push(SystemModuleDraft {
886            name: "后端服务".to_string(),
887            description: "业务逻辑处理".to_string(),
888            module_type: ModuleDraftType::Backend,
889            responsibilities: vec!["API 接口".to_string(), "业务逻辑".to_string()],
890            tech_stack: vec!["Node.js".to_string(), "Express".to_string()],
891            dependencies: vec!["数据库".to_string()],
892        });
893
894        // 数据库模块
895        modules.push(SystemModuleDraft {
896            name: "数据库".to_string(),
897            description: "数据持久化".to_string(),
898            module_type: ModuleDraftType::Database,
899            responsibilities: vec!["数据存储".to_string(), "数据查询".to_string()],
900            tech_stack: vec!["PostgreSQL".to_string()],
901            dependencies: vec![],
902        });
903
904        // 如果有用户相关流程,添加认证模块
905        if has_user_flow {
906            modules.push(SystemModuleDraft {
907                name: "认证服务".to_string(),
908                description: "用户认证和授权".to_string(),
909                module_type: ModuleDraftType::Service,
910                responsibilities: vec!["用户认证".to_string(), "权限管理".to_string()],
911                tech_stack: vec!["JWT".to_string()],
912                dependencies: vec!["数据库".to_string()],
913            });
914        }
915
916        modules
917    }
918
919    /// 处理非功能要求阶段输入
920    #[allow(dead_code)]
921    fn process_nfr_input(&self, state: &mut DialogState, input: &str) {
922        // 解析用户输入的 NFR
923        let input_lower = input.to_lowercase();
924
925        // 性能要求
926        if input_lower.contains("性能")
927            || input_lower.contains("响应")
928            || input_lower.contains("ms")
929        {
930            state.nfrs.push(NFRDraft {
931                category: NFRDraftCategory::Performance,
932                name: "API 响应时间".to_string(),
933                description: "API 平均响应时间应控制在合理范围内".to_string(),
934                priority: NFRDraftPriority::Should,
935                metrics: Some("< 500ms".to_string()),
936            });
937        }
938
939        // 安全要求
940        if input_lower.contains("安全")
941            || input_lower.contains("认证")
942            || input_lower.contains("加密")
943        {
944            state.nfrs.push(NFRDraft {
945                category: NFRDraftCategory::Security,
946                name: "用户认证".to_string(),
947                description: "实现安全的用户认证机制".to_string(),
948                priority: NFRDraftPriority::Must,
949                metrics: None,
950            });
951        }
952
953        // 可用性要求
954        if input_lower.contains("可用") || input_lower.contains("99") {
955            state.nfrs.push(NFRDraft {
956                category: NFRDraftCategory::Availability,
957                name: "系统可用性".to_string(),
958                description: "系统应保持高可用性".to_string(),
959                priority: NFRDraftPriority::Should,
960                metrics: Some("99.9%".to_string()),
961            });
962        }
963
964        // 如果没有解析到 NFR,添加默认值
965        if state.nfrs.is_empty() {
966            state.nfrs = self.get_default_nfrs();
967        }
968    }
969
970    /// 获取默认 NFR
971    #[allow(dead_code)]
972    fn get_default_nfrs(&self) -> Vec<NFRDraft> {
973        vec![
974            NFRDraft {
975                category: NFRDraftCategory::Performance,
976                name: "API 响应时间".to_string(),
977                description: "API 平均响应时间应控制在合理范围内".to_string(),
978                priority: NFRDraftPriority::Should,
979                metrics: Some("< 500ms".to_string()),
980            },
981            NFRDraft {
982                category: NFRDraftCategory::Security,
983                name: "用户认证".to_string(),
984                description: "实现安全的用户认证机制".to_string(),
985                priority: NFRDraftPriority::Must,
986                metrics: None,
987            },
988            NFRDraft {
989                category: NFRDraftCategory::Availability,
990                name: "系统可用性".to_string(),
991                description: "系统应保持高可用性".to_string(),
992                priority: NFRDraftPriority::Should,
993                metrics: Some("99.9%".to_string()),
994            },
995        ]
996    }
997
998    /// 生成摘要
999    #[allow(dead_code)]
1000    fn generate_summary(&self, state: &DialogState) -> String {
1001        let processes_str = state
1002            .business_processes
1003            .iter()
1004            .map(|p| {
1005                let type_str = match p.process_type {
1006                    ProcessDraftType::Core => "核心",
1007                    ProcessDraftType::Support => "支撑",
1008                    ProcessDraftType::Management => "管理",
1009                };
1010                format!("- **{}**({}):{}", p.name, type_str, p.steps.join(" → "))
1011            })
1012            .collect::<Vec<_>>()
1013            .join("\n");
1014
1015        let modules_str = state
1016            .modules
1017            .iter()
1018            .map(|m| {
1019                let type_str = match m.module_type {
1020                    ModuleDraftType::Frontend => "前端",
1021                    ModuleDraftType::Backend => "后端",
1022                    ModuleDraftType::Database => "数据库",
1023                    ModuleDraftType::Service => "服务",
1024                    ModuleDraftType::Infrastructure => "基础设施",
1025                };
1026                format!(
1027                    "- **{}**({}):{}",
1028                    m.name,
1029                    type_str,
1030                    m.responsibilities.join("、")
1031                )
1032            })
1033            .collect::<Vec<_>>()
1034            .join("\n");
1035
1036        let nfrs_str = state
1037            .nfrs
1038            .iter()
1039            .map(|n| {
1040                let priority_str = match n.priority {
1041                    NFRDraftPriority::Must => "MUST",
1042                    NFRDraftPriority::Should => "SHOULD",
1043                    NFRDraftPriority::Could => "COULD",
1044                };
1045                let metrics_str = n
1046                    .metrics
1047                    .as_ref()
1048                    .map(|m| format!("({})", m))
1049                    .unwrap_or_default();
1050                format!(
1051                    "- [{}] {}:{}{}",
1052                    priority_str, n.name, n.description, metrics_str
1053                )
1054            })
1055            .collect::<Vec<_>>()
1056            .join("\n");
1057
1058        format!(
1059            r#"# 蓝图草案:{}
1060
1061## 项目概述
1062{}
1063
1064**目标用户**:{}
1065
1066## 业务流程({} 个)
1067{}
1068
1069## 系统模块({} 个)
1070{}
1071
1072## 非功能要求({} 项)
1073{}
1074
1075---"#,
1076            state.project_name,
1077            state.project_description,
1078            if state.target_users.is_empty() {
1079                "待定".to_string()
1080            } else {
1081                state.target_users.join("、")
1082            },
1083            state.business_processes.len(),
1084            processes_str,
1085            state.modules.len(),
1086            modules_str,
1087            state.nfrs.len(),
1088            nfrs_str
1089        )
1090    }
1091
1092    /// 处理汇总确认阶段输入
1093    #[allow(dead_code)]
1094    fn process_summary_input(&self, state: &mut DialogState, input: &str) -> (String, DialogPhase) {
1095        let normalized = input.trim().to_lowercase();
1096
1097        if normalized == "确认" || normalized == "confirm" || normalized == "yes" {
1098            // 确认,进入完成阶段
1099            (
1100                get_phase_prompt(DialogPhase::Complete).to_string(),
1101                DialogPhase::Complete,
1102            )
1103        } else if normalized == "重来" || normalized == "restart" {
1104            // 重置状态
1105            state.phase = DialogPhase::Welcome;
1106            state.project_name.clear();
1107            state.project_description.clear();
1108            state.target_users.clear();
1109            state.problems_to_solve.clear();
1110            state.business_processes.clear();
1111            state.modules.clear();
1112            state.nfrs.clear();
1113            (
1114                format!(
1115                    "好的,让我们重新开始。\n\n{}",
1116                    get_phase_prompt(DialogPhase::Welcome)
1117                ),
1118                DialogPhase::Welcome,
1119            )
1120        } else {
1121            // 当作修改请求处理
1122            let summary = self.generate_summary(state);
1123            (format!("已记录您的修改意见。\n\n{}\n\n请确认修改后的内容。输入「确认」、「修改 [内容]」或「重来」。", summary), DialogPhase::Summary)
1124        }
1125    }
1126
1127    /// 从状态创建蓝图
1128    pub async fn create_blueprint_from_state(
1129        &self,
1130        state: &DialogState,
1131        blueprint_manager: &mut BlueprintManager,
1132    ) -> Result<Blueprint, String> {
1133        // 创建蓝图
1134        let blueprint = blueprint_manager
1135            .create_blueprint(
1136                state.project_name.clone(),
1137                state.project_description.clone(),
1138            )
1139            .await
1140            .map_err(|e| e.to_string())?;
1141
1142        // 添加业务流程
1143        for process in &state.business_processes {
1144            let bp = BusinessProcess {
1145                id: uuid::Uuid::new_v4().to_string(),
1146                name: process.name.clone(),
1147                description: process.description.clone(),
1148                process_type: ProcessType::ToBe,
1149                steps: process
1150                    .steps
1151                    .iter()
1152                    .enumerate()
1153                    .map(|(i, step)| ProcessStep {
1154                        id: uuid::Uuid::new_v4().to_string(),
1155                        order: i as u32 + 1,
1156                        name: step.clone(),
1157                        description: step.clone(),
1158                        actor: "user".to_string(),
1159                        system_action: None,
1160                        user_action: Some(step.clone()),
1161                        conditions: vec![],
1162                        outcomes: vec![],
1163                    })
1164                    .collect(),
1165                actors: vec!["user".to_string()],
1166                inputs: vec![],
1167                outputs: vec![],
1168            };
1169            blueprint_manager
1170                .add_business_process(&blueprint.id, bp)
1171                .await
1172                .map_err(|e| e.to_string())?;
1173        }
1174
1175        // 添加系统模块
1176        let mut module_id_map: HashMap<String, String> = HashMap::new();
1177
1178        for module in &state.modules {
1179            let sys_module = SystemModule {
1180                id: uuid::Uuid::new_v4().to_string(),
1181                name: module.name.clone(),
1182                description: module.description.clone(),
1183                module_type: module.module_type.into(),
1184                responsibilities: module.responsibilities.clone(),
1185                dependencies: vec![],
1186                interfaces: vec![],
1187                tech_stack: Some(module.tech_stack.clone()),
1188                root_path: None,
1189            };
1190            module_id_map.insert(module.name.clone(), sys_module.id.clone());
1191            blueprint_manager
1192                .add_module(&blueprint.id, sys_module)
1193                .await
1194                .map_err(|e| e.to_string())?;
1195        }
1196
1197        // 添加非功能要求
1198        for nfr in &state.nfrs {
1199            let requirement = NonFunctionalRequirement {
1200                id: uuid::Uuid::new_v4().to_string(),
1201                category: nfr.category.into(),
1202                name: nfr.name.clone(),
1203                description: nfr.description.clone(),
1204                priority: nfr.priority.into(),
1205                metric: nfr.metrics.clone(),
1206            };
1207            blueprint_manager
1208                .add_nfr(&blueprint.id, requirement)
1209                .await
1210                .map_err(|e| e.to_string())?;
1211        }
1212
1213        // 获取更新后的蓝图
1214        let blueprint = blueprint_manager
1215            .get_blueprint(&blueprint.id)
1216            .await
1217            .ok_or_else(|| "无法获取创建的蓝图".to_string())?;
1218
1219        Ok(blueprint)
1220    }
1221
1222    /// 获取对话状态
1223    pub fn get_dialog_state(&self, session_id: &str) -> Option<&DialogState> {
1224        self.sessions.get(session_id)
1225    }
1226
1227    /// 获取当前阶段的提示
1228    pub fn get_current_phase_prompt(&self, session_id: &str) -> String {
1229        self.sessions
1230            .get(session_id)
1231            .map(|s| get_phase_prompt(s.phase).to_string())
1232            .unwrap_or_default()
1233    }
1234
1235    /// 结束对话
1236    pub async fn end_dialog(&mut self, session_id: &str) {
1237        self.sessions.remove(session_id);
1238        self.emit(DialogEvent::Ended {
1239            session_id: session_id.to_string(),
1240        })
1241        .await;
1242    }
1243}
1244
1245// ============================================================================
1246// 工厂函数
1247// ============================================================================
1248
1249/// 创建需求对话管理器
1250pub fn create_requirement_dialog_manager() -> RequirementDialogManager {
1251    RequirementDialogManager::new()
1252}