diff --git a/CodePlay.Core/Models/ConversionModels.cs b/CodePlay.Core/Models/ConversionModels.cs
index 80d5e09..52f0470 100644
--- a/CodePlay.Core/Models/ConversionModels.cs
+++ b/CodePlay.Core/Models/ConversionModels.cs
@@ -115,6 +115,26 @@ public class ConversionResult
///
public class ConversionReport
{
+ ///
+ /// 报告 ID
+ ///
+ public string Id { get; set; } = Guid.NewGuid().ToString("N")[..20];
+
+ ///
+ /// 项目 ID
+ ///
+ public string ProjectId { get; set; } = string.Empty;
+
+ ///
+ /// 源语言
+ ///
+ public LanguageType SourceLanguage { get; set; }
+
+ ///
+ /// 目标语言
+ ///
+ public LanguageType TargetLanguage { get; set; }
+
///
/// 转换的行数
///
@@ -135,6 +155,16 @@ public class ConversionReport
///
public TimeSpan Duration { get; set; }
+ ///
+ /// 问题数量
+ ///
+ public int IssueCount { get; set; }
+
+ ///
+ /// TODO 数量
+ ///
+ public int TodoCount { get; set; }
+
///
/// 问题列表
///
@@ -149,6 +179,21 @@ public class ConversionReport
/// TODO 列表
///
public List TodoItems { get; set; } = new();
+
+ ///
+ /// 验证状态
+ ///
+ public string ValidationStatus { get; set; } = "NotValidated";
+
+ ///
+ /// 最后验证时间
+ ///
+ public DateTime? LastValidatedAt { get; set; }
+
+ ///
+ /// 创建时间
+ ///
+ public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
}
///
diff --git a/CodePlay.Core/Services/ReportStorageService.cs b/CodePlay.Core/Services/ReportStorageService.cs
new file mode 100644
index 0000000..f81353b
--- /dev/null
+++ b/CodePlay.Core/Services/ReportStorageService.cs
@@ -0,0 +1,119 @@
+using System.Collections.Concurrent;
+using System.Text.Json;
+using CodePlay.Core.Models;
+using CodePlay.Core.Common;
+
+namespace CodePlay.Core.Services;
+
+///
+/// 转换报告存储服务(内存版 MVP)
+///
+public interface IReportStorageService
+{
+ Task SaveReportAsync(ConversionReport report, string? projectId = null);
+ Task GetReportAsync(string reportId);
+ Task> GetReportsByProjectAsync(string projectId);
+ Task> GetAllReportsAsync();
+ Task DeleteReportAsync(string reportId);
+ Task GetStatisticsAsync();
+}
+
+public class ReportStorageService : IReportStorageService
+{
+ private readonly ConcurrentDictionary _reports = new();
+ private readonly ConcurrentDictionary _projects = new();
+
+ public Task SaveReportAsync(ConversionReport report, string? projectId = null)
+ {
+ report.Id = Guid.NewGuid().ToString("N")[..20];
+ report.ProjectId = projectId ?? "default";
+ report.CreatedAt = DateTime.UtcNow;
+
+ _reports[report.Id] = report;
+
+ // 更新项目统计
+ if (projectId != null && _projects.ContainsKey(projectId))
+ {
+ _projects[projectId].TotalConversions++;
+ _projects[projectId].UpdatedAt = DateTime.UtcNow;
+ }
+
+ return Task.FromResult(report);
+ }
+
+ public Task GetReportAsync(string reportId)
+ {
+ _reports.TryGetValue(reportId, out var report);
+ return Task.FromResult(report);
+ }
+
+ public Task> GetReportsByProjectAsync(string projectId)
+ {
+ var reports = _reports.Values
+ .Where(r => r.ProjectId == projectId)
+ .OrderByDescending(r => r.CreatedAt)
+ .ToList();
+
+ return Task.FromResult(reports);
+ }
+
+ public Task> GetAllReportsAsync()
+ {
+ var reports = _reports.Values
+ .OrderByDescending(r => r.CreatedAt)
+ .ToList();
+
+ return Task.FromResult(reports);
+ }
+
+ public Task DeleteReportAsync(string reportId)
+ {
+ _reports.TryRemove(reportId, out _);
+ return Task.CompletedTask;
+ }
+
+ public Task GetStatisticsAsync()
+ {
+ var reports = _reports.Values.ToList();
+
+ var statistics = new ConversionStatistics
+ {
+ TotalConversions = reports.Count,
+ TotalProjects = _projects.Count,
+ ConversionsByLanguage = reports.GroupBy(r => r.TargetLanguage)
+ .ToDictionary(g => g.Key, g => g.Count()),
+ AverageLinesConverted = reports.Any() ? reports.Average(r => r.LinesConverted) : 0,
+ TotalIssuesDetected = reports.Sum(r => r.IssueCount),
+ TotalTODOs = reports.Sum(r => r.TodoCount)
+ };
+
+ return Task.FromResult(statistics);
+ }
+}
+
+///
+/// 转换统计信息
+///
+public class ConversionStatistics
+{
+ public int TotalConversions { get; set; }
+ public int TotalProjects { get; set; }
+ public Dictionary ConversionsByLanguage { get; set; } = new();
+ public double AverageLinesConverted { get; set; }
+ public int TotalIssuesDetected { get; set; }
+ public int TotalTODOs { get; set; }
+}
+
+///
+/// 项目信息
+///
+public class ProjectInfo
+{
+ public string Id { get; set; } = Guid.NewGuid().ToString("N")[..20];
+ public string Name { get; set; } = string.Empty;
+ public string Description { get; set; } = string.Empty;
+ public List Languages { get; set; } = new();
+ public int TotalConversions { get; set; }
+ public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
+ public DateTime? UpdatedAt { get; set; }
+}
diff --git a/CodePlay.WebAPI/Controllers/ReportController.cs b/CodePlay.WebAPI/Controllers/ReportController.cs
new file mode 100644
index 0000000..894ce4b
--- /dev/null
+++ b/CodePlay.WebAPI/Controllers/ReportController.cs
@@ -0,0 +1,55 @@
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+using CodePlay.Core.Services;
+using CodePlay.Core.Models;
+
+namespace CodePlay.WebAPI.Controllers;
+
+[ApiController]
+[Route("api/[controller]")]
+[Authorize]
+public class ReportController : ControllerBase
+{
+ private readonly IReportStorageService _storageService;
+
+ public ReportController(IReportStorageService storageService)
+ {
+ _storageService = storageService;
+ }
+
+ [HttpGet]
+ public async Task>> GetAllReports()
+ {
+ var reports = await _storageService.GetAllReportsAsync();
+ return Ok(reports);
+ }
+
+ [HttpGet("{reportId}")]
+ public async Task> GetReport(string reportId)
+ {
+ var report = await _storageService.GetReportAsync(reportId);
+ if (report == null) return NotFound();
+ return Ok(report);
+ }
+
+ [HttpGet("project/{projectId}")]
+ public async Task>> GetReportsByProject(string projectId)
+ {
+ var reports = await _storageService.GetReportsByProjectAsync(projectId);
+ return Ok(reports);
+ }
+
+ [HttpDelete("{reportId}")]
+ public async Task DeleteReport(string reportId)
+ {
+ await _storageService.DeleteReportAsync(reportId);
+ return NoContent();
+ }
+
+ [HttpGet("stats")]
+ public async Task> GetStatistics()
+ {
+ var stats = await _storageService.GetStatisticsAsync();
+ return Ok(stats);
+ }
+}