requirements-analysis
Version:
简化的需求分析MCP服务 - 基于AI软件工程(优化版)6步流程
228 lines (182 loc) • 6.25 kB
text/typescript
/**
* 文件存储管理
*/
import { promises as fs } from 'fs';
import { join, dirname } from 'path';
import { StepResult, AnalysisSession } from '../types';
import { Logger } from '../utils/logger';
export class FileStorage {
private baseDir: string;
private logger: Logger;
constructor(baseDir: string = './outputs', logger: Logger) {
this.baseDir = baseDir;
this.logger = logger;
}
/**
* 确保目录存在
*/
private async ensureDir(dirPath: string): Promise<void> {
try {
await fs.access(dirPath);
} catch {
await fs.mkdir(dirPath, { recursive: true });
}
}
/**
* 获取项目输出目录
*/
getProjectDir(projectName: string): string {
// 清理项目名称,移除特殊字符
const cleanName = projectName.replace(/[<>:"/\\|?*]/g, '-').trim();
return join(this.baseDir, cleanName);
}
/**
* 保存步骤结果
*/
async saveStepResult(session: AnalysisSession, stepResult: StepResult): Promise<string> {
const projectDir = this.getProjectDir(session.projectInfo.projectName);
this.logger.info(
`准备保存步骤${stepResult.stepNumber}结果`,
session.sessionId,
stepResult.stepNumber,
{ projectDir, fileName: stepResult.filePath }
);
await this.ensureDir(projectDir);
const filePath = join(projectDir, stepResult.filePath);
// 生成文档内容
const content = this.generateStepDocument(session, stepResult);
this.logger.info(
`生成文档内容完成`,
session.sessionId,
stepResult.stepNumber,
{ filePath, contentLength: content.length }
);
try {
await fs.writeFile(filePath, content, 'utf-8');
// 验证文件是否真的被创建
const stats = await fs.stat(filePath);
this.logger.info(
`步骤${stepResult.stepNumber}结果已保存`,
session.sessionId,
stepResult.stepNumber,
{ filePath, fileSize: stats.size, absolutePath: require('path').resolve(filePath) }
);
return filePath;
} catch (error) {
this.logger.error(
`保存步骤${stepResult.stepNumber}结果失败`,
session.sessionId,
stepResult.stepNumber,
{ error: error instanceof Error ? error.message : String(error), filePath }
);
throw error;
}
}
/**
* 生成步骤文档内容(优化版:只保存结果)
*/
private generateStepDocument(session: AnalysisSession, stepResult: StepResult): string {
const timestamp = stepResult.timestamp.toLocaleString('zh-CN');
return `# ${stepResult.stepName}
${stepResult.result}
---
*生成时间: ${timestamp} | 项目: ${session.projectInfo.projectName} | 步骤: ${stepResult.stepNumber}/6*
`;
}
/**
* 读取步骤结果
*/
async readStepResult(projectName: string, stepNumber: number): Promise<string | null> {
const projectDir = this.getProjectDir(projectName);
const fileName = `step${stepNumber}-*.md`;
try {
const files = await fs.readdir(projectDir);
const stepFile = files.find(file => file.startsWith(`step${stepNumber}-`));
if (!stepFile) {
return null;
}
const filePath = join(projectDir, stepFile);
return await fs.readFile(filePath, 'utf-8');
} catch {
return null;
}
}
/**
* 列出项目文件
*/
async listProjectFiles(projectName: string): Promise<string[]> {
const projectDir = this.getProjectDir(projectName);
try {
const files = await fs.readdir(projectDir);
return files.filter(file => file.endsWith('.md')).sort();
} catch {
return [];
}
}
/**
* 获取所有项目
*/
async listProjects(): Promise<string[]> {
try {
await this.ensureDir(this.baseDir);
const dirs = await fs.readdir(this.baseDir, { withFileTypes: true });
return dirs
.filter(dirent => dirent.isDirectory())
.map(dirent => dirent.name)
.sort();
} catch {
return [];
}
}
/**
* 保存项目摘要
*/
async saveProjectSummary(session: AnalysisSession): Promise<void> {
const projectDir = this.getProjectDir(session.projectInfo.projectName);
await this.ensureDir(projectDir);
const summaryPath = join(projectDir, 'README.md');
const content = this.generateProjectSummary(session);
await fs.writeFile(summaryPath, content, 'utf-8');
this.logger.info(
'项目摘要已保存',
session.sessionId,
undefined,
{ summaryPath }
);
}
/**
* 生成项目摘要
*/
private generateProjectSummary(session: AnalysisSession): string {
const completedSteps = Array.from(session.stepResults.keys()).sort();
const progress = Math.round((completedSteps.length / session.totalSteps) * 100);
return `# ${session.projectInfo.projectName} - 需求分析报告
## 📋 项目信息
- **项目名称**: ${session.projectInfo.projectName}
- **项目类型**: ${session.projectInfo.projectType}
- **所属行业**: ${session.projectInfo.industry}
- **开始时间**: ${session.startTime.toLocaleString('zh-CN')}
- **最后更新**: ${session.lastUpdateTime.toLocaleString('zh-CN')}
- **完成进度**: ${progress}% (${completedSteps.length}/${session.totalSteps})
- **状态**: ${session.isComplete ? '已完成' : '进行中'}
## 🎯 项目背景
${session.projectInfo.background}
## 🚀 核心目标
${session.projectInfo.objectives}
## 📁 文档列表
${completedSteps.map(stepNum => {
const stepResult = session.stepResults.get(stepNum);
return `- [第${stepNum}步:${stepResult?.stepName}](${stepResult?.filePath})`;
}).join('\n')}
## 📊 分析流程
1. ✅ 项目基础信息填写 (5分钟)
2. ${completedSteps.includes(2) ? '✅' : '⏳'} AI智能分析项目全貌 (10分钟)
3. ${completedSteps.includes(3) ? '✅' : '⏳'} 生成需求分析文档初版 (10分钟)
4. ${completedSteps.includes(4) ? '✅' : '⏳'} AI质量分析 (8分钟)
5. ${completedSteps.includes(5) ? '✅' : '⏳'} 生成改进建议 (5分钟)
6. ${completedSteps.includes(6) ? '✅' : '⏳'} 生成最终文档 (10分钟)
---
*此报告由需求分析MCP服务自动生成*
`;
}
}