namespace Dpz.Core.Service.RepositoryServiceImpl;

public class CodeNoteService(
    IRepository<CodeNote> repository,
    IMapper mapper,
    IConfiguration configuration
) : ICodeNoteService
{
    public async Task<string> SaveNoteAsync(string[]? path, string name, string? note)
    {
        var codeNote = await BuildFluent(path, name, out var pathStr).FirstOrDefaultAsync();
        if (codeNote == null)
        {
            var entity = new CodeNote
            {
                CreateTime = DateTime.Now,
                LastUpdateTime = DateTime.Now,
                Name = name,
                Note = note,
                Path = pathStr,
            };
            await repository.InsertAsync(entity);
            return entity.Id.ToString();
        }

        codeNote.Note = note;
        codeNote.LastUpdateTime = DateTime.Now;
        await repository.UpdateAsync(codeNote);
        return codeNote.Id.ToString();
    }

    public async Task<VmCodeNote?> FindAsync(string[]? path, string? name)
    {
        if (string.IsNullOrWhiteSpace(name))
        {
            return null;
        }
        var codeNote = await BuildFluent(path, name, out _).FirstOrDefaultAsync();

        if (codeNote == null)
        {
            return null;
        }

        return mapper.Map<VmCodeNote>(codeNote);
    }

    private static string GetPathStr(string[]? path)
    {
        return path is not null && path.Length > 0 ? string.Join("/", path) : "";
    }

    private static FilterDefinition<CodeNote> BuildFilter(
        string[]? path,
        string? name,
        out string pathStr
    )
    {
        pathStr = GetPathStr(path);
        return Builders<CodeNote>.Filter.And(
            Builders<CodeNote>.Filter.Eq(x => x.Path, pathStr),
            Builders<CodeNote>.Filter.Eq(x => x.Name, name)
        );
    }

    private IFindFluent<CodeNote, CodeNote> BuildFluent(
        string[]? path,
        string name,
        out string pathStr
    )
    {
        var filter = BuildFilter(path, name, out pathStr);
        return repository.SearchFor(
            filter,
            new FindOptions
            {
                Collation = new Collation(
                    locale: "en",
                    strength: new Optional<CollationStrength?>(CollationStrength.Secondary)
                ),
            }
        );
    }

    public async Task SaveAiAnalyzeResultAsync(string[]? path, string name, string analyzeResult)
    {
        var codeNote = await BuildFluent(path, name, out var pathStr).FirstOrDefaultAsync();
        if (codeNote == null)
        {
            var entity = new CodeNote
            {
                CreateTime = DateTime.Now,
                LastUpdateTime = DateTime.Now,
                Name = name,
                AiAnalyzeResult = analyzeResult,
                Path = pathStr,
            };
            await repository.InsertAsync(entity);
            return;
        }

        codeNote.AiAnalyzeResult = analyzeResult;
        codeNote.LastUpdateTime = DateTime.Now;
        await repository.UpdateAsync(codeNote);
    }

    public async Task<bool> ShouldAnalyzeAsync(
        string[]? path,
        string? name,
        CodeContainer? codeContainer
    )
    {
        var useAiAnalyze = configuration.GetValue("CodeUseAIAnalyze", false);
        if (!useAiAnalyze)
        {
            return false;
        }

        if (
            codeContainer is not { Language: "csharp" }
            || string.IsNullOrWhiteSpace(codeContainer.CodeContent)
            || string.IsNullOrWhiteSpace(name)
        )
        {
            return false;
        }

        // 检查代码行数,少于50行不分析
        var lineCount = codeContainer
            .CodeContent.Split(["\r\n", "\r", "\n"], StringSplitOptions.None)
            .Length;
        if (lineCount < 50)
        {
            return false;
        }

        var codeNote = await FindAsync(path, name);
        if (string.IsNullOrWhiteSpace(codeContainer.AiAnalyzeResult))
        {
            return true;
        }

        if (codeNote == null)
        {
            return false;
        }

        return DateTime.Now - codeNote.LastUpdateTime > TimeSpan.FromDays(30);
    }

    public async Task<List<VmCodeNote>> GetNoteAsync(string[]? path)
    {
        var pathStr = GetPathStr(path);
        var filter = Builders<CodeNote>.Filter.Eq(x => x.Path, pathStr);
        var list = await repository
            .SearchFor(
                filter,
                new FindOptions
                {
                    Collation = new Collation(
                        locale: "en",
                        strength: new Optional<CollationStrength?>(CollationStrength.Secondary)
                    ),
                }
            )
            .ToListAsync();
        return mapper.Map<List<VmCodeNote>>(list);
    }

    public async Task<List<VmCodeNote>> GetAllNoteAsync()
    {
        var list = await repository.SearchFor(x => true).ToListAsync();
        return mapper.Map<List<VmCodeNote>>(list);
    }

    public async Task DeleteAsync(string[]? path, string name)
    {
        var filter = BuildFilter(path, name, out _);
        await repository.DeleteAsync(filter);
    }
}
⚠⚠    以下内容为AI分析的结果,请根据实际情况进行判断。

这是一个代码笔记服务类 CodeNoteService,实现了 ICodeNoteService 接口。该服务主要用于管理代码文件的笔记和AI分析结果。让我详细解释其功能:

类结构

  • 使用依赖注入接收三个服务:
    • IRepository<CodeNote>:数据库操作仓储
    • IMapper:对象映射器(如AutoMapper)
    • IConfiguration:配置服务

主要功能

1. 保存笔记 (SaveNoteAsync)

  • 根据路径和名称查找已存在的笔记
  • 如果不存在,创建新的 CodeNote 实体并插入数据库
  • 如果存在,更新笔记内容和最后更新时间
  • 返回记录的ID

2. 查找笔记 (FindAsync)

  • 根据路径和名称查找笔记
  • 返回映射后的视图模型 VmCodeNote

3. AI分析功能

  • SaveAiAnalyzeResultAsync:保存AI分析结果
  • ShouldAnalyzeAsync:判断是否需要进行AI分析
    • 检查配置是否启用AI分析
    • 只分析C#代码
    • 只分析50行以上的代码
    • 如果已有分析结果且超过30天,则重新分析

4. 批量查询

  • GetNoteAsync:根据路径获取该路径下的所有笔记
  • GetAllNoteAsync:获取所有笔记

5. 删除功能 (DeleteAsync)

  • 根据路径和名称删除笔记

核心辅助方法

GetPathStr

将路径数组转换为字符串(用"/"连接)

BuildFilter

构建MongoDB查询过滤器,同时匹配路径和名称

BuildFluent

构建MongoDB查询对象,包含排序规则配置:

  • 使用英文语言环境
  • 设置为二级强度比较(忽略大小写和重音符号)

技术特点

  1. 异步操作:所有数据库操作都是异步的
  2. MongoDB支持:使用MongoDB的FilterDefinition和FindOptions
  3. 国际化支持:配置了英文排序规则
  4. 智能AI分析:根据代码特征和时间策略决定是否需要AI分析
  5. 对象映射:使用Mapper进行实体和视图模型的转换

这个服务是一个完整的代码笔记管理系统的核心业务逻辑层,提供了CRUD操作和智能AI分析功能。

评论加载中...