918bbed0fc
- 修复 deps.py 中 get_vn_service 的引用错误 (vn_service.vn_service -> vn_service) - 移除登录页面上的明文密码提示 - 改进前端错误处理,避免数据加载失败导致登录显示错误
303 lines
7.7 KiB
JavaScript
303 lines
7.7 KiB
JavaScript
/**
|
|
* 需求追踪模块
|
|
*
|
|
* 追踪需求到设计和编码的映射,生成一致性检查报告
|
|
*/
|
|
|
|
/**
|
|
* 需求追踪器类
|
|
*/
|
|
export class RequirementTracker {
|
|
constructor() {
|
|
this.requirements = new Map() // id -> requirement
|
|
this.designMapping = new Map() // requirementId -> designItems
|
|
this.codeMapping = new Map() // requirementId -> codeItems
|
|
}
|
|
|
|
/**
|
|
* 添加需求
|
|
*/
|
|
addRequirement(id, requirement) {
|
|
this.requirements.set(id, {
|
|
id,
|
|
description: typeof requirement === 'string' ? requirement : requirement.description || requirement.text || JSON.stringify(requirement),
|
|
status: 'pending',
|
|
...requirement
|
|
})
|
|
}
|
|
|
|
/**
|
|
* 添加设计映射
|
|
*/
|
|
addDesignMapping(requirementId, designItems) {
|
|
this.designMapping.set(requirementId, Array.isArray(designItems) ? designItems : [designItems])
|
|
|
|
// 更新需求状态
|
|
const req = this.requirements.get(requirementId)
|
|
if (req) {
|
|
req.status = 'designed'
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 添加编码映射
|
|
*/
|
|
addCodeMapping(requirementId, codeItems) {
|
|
this.codeMapping.set(requirementId, Array.isArray(codeItems) ? codeItems : [codeItems])
|
|
|
|
// 更新需求状态
|
|
const req = this.requirements.get(requirementId)
|
|
if (req) {
|
|
req.status = 'implemented'
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 获取需求
|
|
*/
|
|
getRequirement(id) {
|
|
return this.requirements.get(id)
|
|
}
|
|
|
|
/**
|
|
* 获取所有需求
|
|
*/
|
|
getAllRequirements() {
|
|
return Array.from(this.requirements.values())
|
|
}
|
|
|
|
/**
|
|
* 获取需求的设计映射
|
|
*/
|
|
getDesignMapping(requirementId) {
|
|
return this.designMapping.get(requirementId) || []
|
|
}
|
|
|
|
/**
|
|
* 获取需求的编码映射
|
|
*/
|
|
getCodeMapping(requirementId) {
|
|
return this.codeMapping.get(requirementId) || []
|
|
}
|
|
|
|
/**
|
|
* 检查需求的完整性
|
|
*/
|
|
checkCompleteness(requirementId) {
|
|
const req = this.getRequirement(requirementId)
|
|
if (!req) {
|
|
return { complete: false, reason: '需求不存在' }
|
|
}
|
|
|
|
const hasDesign = this.designMapping.has(requirementId)
|
|
const hasCode = this.codeMapping.has(requirementId)
|
|
|
|
if (!hasDesign) {
|
|
return { complete: false, reason: '缺少设计映射' }
|
|
}
|
|
|
|
if (!hasCode) {
|
|
return { complete: false, reason: '缺少编码映射' }
|
|
}
|
|
|
|
return { complete: true }
|
|
}
|
|
|
|
/**
|
|
* 生成追踪报告
|
|
*/
|
|
generateReport() {
|
|
const requirements = this.getAllRequirements()
|
|
const report = {
|
|
total: requirements.length,
|
|
pending: 0,
|
|
designed: 0,
|
|
implemented: 0,
|
|
items: []
|
|
}
|
|
|
|
for (const req of requirements) {
|
|
const completeness = this.checkCompleteness(req.id)
|
|
const designItems = this.getDesignMapping(req.id)
|
|
const codeItems = this.getCodeMapping(req.id)
|
|
|
|
if (req.status === 'pending') {
|
|
report.pending++
|
|
} else if (req.status === 'designed') {
|
|
report.designed++
|
|
} else if (req.status === 'implemented') {
|
|
report.implemented++
|
|
}
|
|
|
|
report.items.push({
|
|
id: req.id,
|
|
description: req.description,
|
|
status: req.status,
|
|
complete: completeness.complete,
|
|
designCount: designItems.length,
|
|
codeCount: codeItems.length,
|
|
designItems,
|
|
codeItems
|
|
})
|
|
}
|
|
|
|
return report
|
|
}
|
|
|
|
/**
|
|
* 导出为 Markdown 格式
|
|
*/
|
|
toMarkdown() {
|
|
const report = this.generateReport()
|
|
let md = '# 需求追踪报告\n\n'
|
|
md += `## 概述\n\n`
|
|
md += `- 总需求数: ${report.total}\n`
|
|
md += `- 待处理: ${report.pending}\n`
|
|
md += `- 已设计: ${report.designed}\n`
|
|
md += `- 已实现: ${report.implemented}\n\n`
|
|
|
|
md += `## 详细追踪\n\n`
|
|
|
|
for (const item of report.items) {
|
|
md += `### ${item.id}: ${item.description}\n\n`
|
|
md += `- **状态**: ${item.status}\n`
|
|
md += `- **完整**: ${item.complete ? '✅' : '❌'}\n`
|
|
md += `- **设计映射**: ${item.designCount} 项\n`
|
|
md += `- **编码映射**: ${item.codeCount} 项\n\n`
|
|
|
|
if (item.designItems.length > 0) {
|
|
md += `#### 设计映射\n\n`
|
|
for (const design of item.designItems) {
|
|
md += `- ${typeof design === 'string' ? design : JSON.stringify(design)}\n`
|
|
}
|
|
md += `\n`
|
|
}
|
|
|
|
if (item.codeItems.length > 0) {
|
|
md += `#### 编码映射\n\n`
|
|
for (const code of item.codeItems) {
|
|
md += `- ${typeof code === 'string' ? code : JSON.stringify(code)}\n`
|
|
}
|
|
md += `\n`
|
|
}
|
|
}
|
|
|
|
return md
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 创建需求追踪器
|
|
*/
|
|
export function createRequirementTracker() {
|
|
return new RequirementTracker()
|
|
}
|
|
|
|
/**
|
|
* 从一致性检查结果生成追踪数据
|
|
*
|
|
* @param {Object} checkResult - 一致性检查结果
|
|
* @returns {Object} 追踪数据
|
|
*/
|
|
export function extractTrackingData(checkResult) {
|
|
const tracker = new RequirementTracker()
|
|
|
|
// 从需求→设计检查中提取需求
|
|
if (checkResult.requirementDesign) {
|
|
for (const item of checkResult.requirementDesign.items) {
|
|
const id = item.check.replace('需求 ', '')
|
|
tracker.addRequirement(id, item.expected)
|
|
if (item.passed) {
|
|
tracker.addDesignMapping(id, [item.actual])
|
|
}
|
|
}
|
|
}
|
|
|
|
// 从需求→编码检查中提取编码映射
|
|
if (checkResult.requirementCode) {
|
|
for (const item of checkResult.requirementCode.items) {
|
|
const id = item.check.replace('需求 ', '')
|
|
if (item.passed) {
|
|
tracker.addCodeMapping(id, [item.actual])
|
|
}
|
|
}
|
|
}
|
|
|
|
return tracker.generateReport()
|
|
}
|
|
|
|
/**
|
|
* 生成一致性检查报告
|
|
*
|
|
* @param {Object} checkResult - 一致性检查结果
|
|
* @returns {string} Markdown 报告
|
|
*/
|
|
export function generateConsistencyReport(checkResult) {
|
|
let md = '# 三向一致性检查报告\n\n'
|
|
|
|
// 概述
|
|
md += `## 概述\n\n`
|
|
md += `- **总体结果**: ${checkResult.allPassed ? '✅ 通过' : '❌ 未通过'}\n`
|
|
md += `- **需求→设计**: ${checkResult.requirementDesign.passed ? '✅ 通过' : '❌ 未通过'}\n`
|
|
md += `- **设计→编码**: ${checkResult.designCode.passed ? '✅ 通过' : '❌ 未通过'}\n`
|
|
md += `- **需求→编码**: ${checkResult.requirementCode.passed ? '✅ 通过' : '❌ 未通过'}\n\n`
|
|
|
|
// 需求→设计详细结果
|
|
md += `## 1️⃣ 需求 → 设计\n\n`
|
|
md += generateCheckTable(checkResult.requirementDesign.items)
|
|
md += `\n${checkResult.requirementDesign.summary}\n\n`
|
|
|
|
// 设计→编码详细结果
|
|
md += `## 2️⃣ 设计 → 编码\n\n`
|
|
md += generateCheckTable(checkResult.designCode.items)
|
|
md += `\n${checkResult.designCode.summary}\n\n`
|
|
|
|
// 需求→编码详细结果
|
|
md += `## 3️⃣ 需求 → 编码\n\n`
|
|
md += generateCheckTable(checkResult.requirementCode.items)
|
|
md += `\n${checkResult.requirementCode.summary}\n\n`
|
|
|
|
// 偏差列表
|
|
if (checkResult.deviations && checkResult.deviations.length > 0) {
|
|
md += `## ⚠️ 发现的偏差\n\n`
|
|
for (const deviation of checkResult.deviations) {
|
|
md += `### ${deviation.type}\n\n`
|
|
for (const issue of deviation.issues) {
|
|
md += `- **${issue.check}**: ${issue.expected} ≠ ${issue.actual}\n`
|
|
}
|
|
md += `\n`
|
|
}
|
|
}
|
|
|
|
return md
|
|
}
|
|
|
|
/**
|
|
* 辅助函数:生成检查表格
|
|
*/
|
|
function generateCheckTable(items) {
|
|
if (!items || items.length === 0) {
|
|
return '无检查项\n'
|
|
}
|
|
|
|
let table = '| 检查项 | 预期 | 实际 | 状态 |\n'
|
|
table += '|--------|------|------|------|\n'
|
|
|
|
for (const item of items) {
|
|
const status = item.passed ? '✅' : '❌'
|
|
table += `| ${item.check} | ${item.expected} | ${item.actual} | ${status} |\n`
|
|
}
|
|
|
|
return table
|
|
}
|
|
|
|
/**
|
|
* 导出默认函数
|
|
*/
|
|
export default {
|
|
RequirementTracker,
|
|
createRequirementTracker,
|
|
extractTrackingData,
|
|
generateConsistencyReport
|
|
}
|