feat: 完成第一批高优先级任务 (Task 4.5, 4.7, 7.3)
Task 4.5 - 转换界面完善: - ConverterView.vue: 完整转换界面 - 集成 Monaco Editor 代码编辑器 - 语言选择器 (C#/Java) - 验证轮次选择 (1-3 轮) - 转换结果显示 - 转换报告弹窗 (TODO 和问题) - 光标位置显示 - 复制结果功能 - 状态栏统计 Task 4.7 - 项目管理界面: - ProjectView.vue: 项目管理页面 - 项目列表展示 - 新建项目对话框 - 项目详情和转换历史 - 项目删除功能 - 路由配置更新 Task 7.3 - 数据库持久化: - CodePlay.Persistence 项目创建 - AppDbContext: SQLite DbContext - ConversionReport 和 ProjectInfo 数据模型 - DatabaseStorageService: IReportStorageService 实现 - 支持报告存储、查询、删除 - 统计信息聚合 - AddPersistence 扩展方法 测试:42 个测试(41 通过,1 跳过)✅ 新增文件: - CodePlay.Web/src/views/ConverterView.vue - CodePlay.Web/src/views/ProjectView.vue - CodePlay.Persistence/AppDbContext.cs - CodePlay.Persistence/DatabaseStorageService.cs - CodePlay.Web/src/router/index.ts (更新) Co-authored-by: monkeycode-ai <monkeycode-ai@chaitin.com>
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using CodePlay.Core.Models;
|
||||
|
||||
namespace CodePlay.Persistence;
|
||||
|
||||
public class AppDbContext : DbContext
|
||||
{
|
||||
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }
|
||||
|
||||
public DbSet<ConversionReport> ConversionReports { get; set; }
|
||||
public DbSet<ProjectInfo> Projects { get; set; }
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
modelBuilder.Entity<ConversionReport>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.Id);
|
||||
entity.Property(e => e.Id).HasMaxLength(50);
|
||||
entity.Property(e => e.ProjectId).HasMaxLength(50);
|
||||
entity.HasIndex(e => e.ProjectId);
|
||||
entity.HasIndex(e => e.CreatedAt);
|
||||
});
|
||||
|
||||
modelBuilder.Entity<ProjectInfo>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.Id);
|
||||
entity.Property(e => e.Id).HasMaxLength(50);
|
||||
entity.Property(e => e.Name).HasMaxLength(200);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\CodePlay.Core\CodePlay.Core.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,102 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using CodePlay.Core.Models;
|
||||
using CodePlay.Core.Services;
|
||||
using CodePlay.Core.Common;
|
||||
|
||||
namespace CodePlay.Persistence;
|
||||
|
||||
public class DatabaseStorageService : IReportStorageService
|
||||
{
|
||||
private readonly AppDbContext _context;
|
||||
|
||||
public DatabaseStorageService(AppDbContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<ConversionReport> SaveReportAsync(ConversionReport report, string? projectId = null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(report.Id))
|
||||
report.Id = Guid.NewGuid().ToString("N")[..20];
|
||||
|
||||
report.ProjectId = projectId ?? "default";
|
||||
report.CreatedAt = DateTime.UtcNow;
|
||||
|
||||
_context.ConversionReports.Add(report);
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
// 更新项目统计
|
||||
if (projectId != null)
|
||||
{
|
||||
var project = await _context.Projects.FindAsync(projectId);
|
||||
if (project != null)
|
||||
{
|
||||
project.TotalConversions++;
|
||||
project.UpdatedAt = DateTime.UtcNow;
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
|
||||
return report;
|
||||
}
|
||||
|
||||
public async Task<ConversionReport?> GetReportAsync(string reportId)
|
||||
{
|
||||
return await _context.ConversionReports.FindAsync(reportId);
|
||||
}
|
||||
|
||||
public async Task<List<ConversionReport>> GetReportsByProjectAsync(string projectId)
|
||||
{
|
||||
return await _context.ConversionReports
|
||||
.Where(r => r.ProjectId == projectId)
|
||||
.OrderByDescending(r => r.CreatedAt)
|
||||
.ToListAsync();
|
||||
}
|
||||
|
||||
public async Task<List<ConversionReport>> GetAllReportsAsync()
|
||||
{
|
||||
return await _context.ConversionReports
|
||||
.OrderByDescending(r => r.CreatedAt)
|
||||
.ToListAsync();
|
||||
}
|
||||
|
||||
public async Task DeleteReportAsync(string reportId)
|
||||
{
|
||||
var report = await _context.ConversionReports.FindAsync(reportId);
|
||||
if (report != null)
|
||||
{
|
||||
_context.ConversionReports.Remove(report);
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<ConversionStatistics> GetStatisticsAsync()
|
||||
{
|
||||
var reports = await _context.ConversionReports.ToListAsync();
|
||||
var projects = await _context.Projects.ToListAsync();
|
||||
|
||||
return 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)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public static class PersistenceServiceExtensions
|
||||
{
|
||||
public static IServiceCollection AddPersistence(this IServiceCollection services, string connectionString)
|
||||
{
|
||||
services.AddDbContext<AppDbContext>(options =>
|
||||
options.UseSqlite(connectionString));
|
||||
|
||||
services.AddScoped<IReportStorageService, DatabaseStorageService>();
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user