143 lines
4.1 KiB
Markdown
143 lines
4.1 KiB
Markdown
# Step 14 — Phase 4.6: 报告导出
|
||
|
||
**依赖**: Step 12(Merger)
|
||
**参考设计**: §14.2
|
||
|
||
## 目标
|
||
|
||
将 `MergedReport` 导出为 Markdown 格式报告。
|
||
|
||
## 新建文件
|
||
|
||
| # | 文件 | 说明 |
|
||
|---|------|------|
|
||
| 1 | `src/utils/report.ts` | `reportToMarkdown()` |
|
||
|
||
---
|
||
|
||
## `src/utils/report.ts`
|
||
|
||
```typescript
|
||
import { MergedReport } from '../merger/merger';
|
||
|
||
function severityEmoji(severity: string): string {
|
||
switch (severity) {
|
||
case 'error': return '🔴';
|
||
case 'warning': return '🟡';
|
||
case 'info': return '🔵';
|
||
default: return '⚪';
|
||
}
|
||
}
|
||
|
||
function formatLine(line: number): string {
|
||
return `L${line + 1}`;
|
||
}
|
||
|
||
export function reportToMarkdown(report: MergedReport): string {
|
||
const lines: string[] = [];
|
||
|
||
lines.push('# 代码审查报告');
|
||
lines.push('');
|
||
lines.push(`**文件:** \`${report.filePath}\``);
|
||
lines.push(`**语言:** ${report.language}`);
|
||
lines.push(`**耗时:** ${(report.duration / 1000).toFixed(1)}s`);
|
||
if (report.adapterNames.length > 0) {
|
||
lines.push(`**分析工具:** ${report.adapterNames.join(', ')}`);
|
||
}
|
||
if (report.degraded) {
|
||
lines.push('');
|
||
lines.push('> ⚠️ 部分 AI 功能不可用,报告已降级');
|
||
}
|
||
if (report.errors.length > 0) {
|
||
lines.push('');
|
||
lines.push('## 错误');
|
||
for (const err of report.errors) {
|
||
lines.push(`- ${err}`);
|
||
}
|
||
}
|
||
|
||
lines.push('');
|
||
lines.push('---');
|
||
lines.push('');
|
||
|
||
const total = report.linterCount + report.customRuleCount + report.aiCount;
|
||
const errors = report.linterDiagnostics.filter(d => d.severity === 'error').length
|
||
+ report.customRuleDiagnostics.filter(d => d.severity === 'error').length
|
||
+ report.aiFindings.filter(f => f.severity === 'error').length;
|
||
const warnings = report.linterDiagnostics.filter(d => d.severity === 'warning').length
|
||
+ report.customRuleDiagnostics.filter(d => d.severity === 'warning').length
|
||
+ report.aiFindings.filter(f => f.severity === 'warning').length;
|
||
const infos = total - errors - warnings;
|
||
|
||
lines.push(`**总计:** ${total} | **错误:** ${errors} | **警告:** ${warnings} | **建议:** ${infos}`);
|
||
lines.push('');
|
||
|
||
if (report.linterDiagnostics.length > 0) {
|
||
lines.push(`## 🔧 静态分析 · ${report.linterCount} 个问题`);
|
||
lines.push('');
|
||
for (const diag of report.linterDiagnostics) {
|
||
lines.push(`- ${severityEmoji(diag.severity)} \`${diag.ruleId}\` ${formatLine(diag.range.start.line)}`);
|
||
lines.push(` ${diag.message}`);
|
||
if (diag.suggestion) {
|
||
lines.push(` 建议: ${diag.suggestion}`);
|
||
}
|
||
}
|
||
lines.push('');
|
||
}
|
||
|
||
if (report.customRuleDiagnostics.length > 0) {
|
||
lines.push(`## 📋 自定义规则 · ${report.customRuleCount} 个问题`);
|
||
lines.push('');
|
||
for (const diag of report.customRuleDiagnostics) {
|
||
lines.push(`- ${severityEmoji(diag.severity)} \`${diag.ruleId}\` ${formatLine(diag.range.start.line)}`);
|
||
lines.push(` ${diag.message}`);
|
||
}
|
||
lines.push('');
|
||
}
|
||
|
||
if (report.aiFindings.length > 0) {
|
||
lines.push(`## 🤖 AI 审查 · ${report.aiCount} 条建议`);
|
||
lines.push('');
|
||
for (const finding of report.aiFindings) {
|
||
lines.push(`- ${severityEmoji(finding.severity)} [AI] [${finding.category}] \`${finding.ruleId}\` ${formatLine(finding.line)}`);
|
||
lines.push(` **${finding.title}**`);
|
||
lines.push(` ${finding.description}`);
|
||
if (finding.suggestion) {
|
||
lines.push(` 建议: ${finding.suggestion}`);
|
||
}
|
||
if (finding.codeDiff) {
|
||
lines.push(' ```diff');
|
||
lines.push(` ${finding.codeDiff.split('\n').join('\n ')}`);
|
||
lines.push(' ```');
|
||
}
|
||
}
|
||
lines.push('');
|
||
}
|
||
|
||
if (total === 0) {
|
||
lines.push('✅ 未发现问题');
|
||
lines.push('');
|
||
}
|
||
|
||
return lines.join('\n');
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 关键逻辑
|
||
|
||
- 报告格式与设计 §14.2 一致
|
||
- 按来源分三个段:静态分析 / 自定义规则 / AI 审查
|
||
- 统计卡片:总计 + 按严重级别拆分
|
||
- AI 审查结果包含 category、codeDiff(diff 代码块)
|
||
- 降级和错误信息在报告顶部单独显示
|
||
|
||
---
|
||
|
||
## 验收
|
||
|
||
- [ ] 文件创建完成
|
||
- [ ] `npm run compile` 通过
|
||
- [ ] `npm run lint` 通过
|