docs: 补全 C# XML 文档注释,覆盖所有公开与内部成员
为 14 个项目中缺少 XML 注释的类、接口、方法、属性、字段、record、 枚举等成员补全中文文档注释。接口方法在接口层定义完整注释,实现类 使用 <inheritdoc /> 引用。私有辅助方法结合业务语义编写注释。 扫描结果:missing-csharp-docs.txt 缺失项归零。 构建结果:0 警告,0 错误。 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -7,11 +7,21 @@ using System.Text;
|
||||
|
||||
namespace FileShare_Services.Services.FileLibrary
|
||||
{
|
||||
/// <summary>
|
||||
/// 文件库核心业务服务,实现磁盘枚举、目录管理、文件扫描与检索。
|
||||
/// </summary>
|
||||
public sealed class FileLibraryService(AppDataContext db) : IFileLibraryService
|
||||
{
|
||||
/// <summary>
|
||||
/// 默认扫描间隔(分钟),当请求未指定间隔时使用。
|
||||
/// </summary>
|
||||
private const int DefaultScanIntervalMinutes = 5;
|
||||
/// <summary>
|
||||
/// 文本预览最大读取字节数(1 MB)。
|
||||
/// </summary>
|
||||
private const int MaxTextPreviewBytes = 1024 * 1024;
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<List<DriveDto>> GetDrivesAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
var drives = DriveInfo.GetDrives()
|
||||
@@ -29,6 +39,7 @@ namespace FileShare_Services.Services.FileLibrary
|
||||
return Task.FromResult(drives);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<List<DirectoryDto>> GetDirectoriesAsync(string? path, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var normalized = NormalizeExistingDirectory(path);
|
||||
@@ -41,6 +52,7 @@ namespace FileShare_Services.Services.FileLibrary
|
||||
return Task.FromResult(directories);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<List<LibraryRootDto>> GetRootsAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
var counts = await db.ManagedFileRecords
|
||||
@@ -56,6 +68,7 @@ namespace FileShare_Services.Services.FileLibrary
|
||||
return roots.Select(root => ToRootDto(root, counts.GetValueOrDefault(root.Id))).ToList();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<LibraryRootDto> AddRootAsync(AddLibraryRootRequest request, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var normalized = NormalizeExistingDirectory(request.Path);
|
||||
@@ -85,6 +98,7 @@ namespace FileShare_Services.Services.FileLibrary
|
||||
return await ScanRootAsync(root.Id, cancellationToken);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<LibraryRootDto> SetRootEnabledAsync(UpdateLibraryRootRequest request, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var root = await db.ManagedLibraryRoots.FirstOrDefaultAsync(item => item.Id == request.Id, cancellationToken)
|
||||
@@ -97,6 +111,7 @@ namespace FileShare_Services.Services.FileLibrary
|
||||
return ToRootDto(root, count);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task DeleteRootAsync(DeleteLibraryRootRequest request, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var root = await db.ManagedLibraryRoots.FirstOrDefaultAsync(item => item.Id == request.Id, cancellationToken)
|
||||
@@ -106,6 +121,7 @@ namespace FileShare_Services.Services.FileLibrary
|
||||
await db.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<LibraryRootDto> ScanRootAsync(int rootId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var root = await db.ManagedLibraryRoots.FirstOrDefaultAsync(item => item.Id == rootId, cancellationToken)
|
||||
@@ -186,6 +202,7 @@ namespace FileShare_Services.Services.FileLibrary
|
||||
return ToRootDto(root, count);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task ScanDueRootsAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
@@ -213,6 +230,7 @@ namespace FileShare_Services.Services.FileLibrary
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<PagedResponse<FileRecordDto>> SearchFilesAsync(SearchFilesRequest request, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var page = Math.Clamp(request.Page, 1, 100000);
|
||||
@@ -252,6 +270,7 @@ namespace FileShare_Services.Services.FileLibrary
|
||||
return PagedResponse<FileRecordDto>.From(items, total, page, pageSize);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<FileRecordDto?> GetFileAsync(int id, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return await db.ManagedFileRecords
|
||||
@@ -261,6 +280,7 @@ namespace FileShare_Services.Services.FileLibrary
|
||||
.FirstOrDefaultAsync(cancellationToken);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<BrowseDirectoryResponse> BrowseDirectoryAsync(BrowseDirectoryRequest request, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var rootId = request.RootId;
|
||||
@@ -309,6 +329,7 @@ namespace FileShare_Services.Services.FileLibrary
|
||||
currentFiles);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<TextPreviewDto?> GetTextPreviewAsync(int id, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var file = await db.ManagedFileRecords
|
||||
@@ -335,6 +356,12 @@ namespace FileShare_Services.Services.FileLibrary
|
||||
return new TextPreviewDto(file.Id, file.FileName, content, stream.Length > MaxTextPreviewBytes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 深度优先遍历目录树,枚举所有被 <see cref="MediaFileTypes"/> 支持的媒体文件路径。
|
||||
/// 遇到无权限的目录时跳过该分支继续遍历。
|
||||
/// </summary>
|
||||
/// <param name="rootPath">根目录路径。</param>
|
||||
/// <returns>支持的文件完整路径枚举。</returns>
|
||||
private static IEnumerable<string> EnumerateSupportedFiles(string rootPath)
|
||||
{
|
||||
var pending = new Stack<string>();
|
||||
@@ -371,6 +398,13 @@ namespace FileShare_Services.Services.FileLibrary
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 规范化目录路径并验证目录存在。
|
||||
/// </summary>
|
||||
/// <param name="path">原始路径。</param>
|
||||
/// <returns>规范化后的完整路径。</returns>
|
||||
/// <exception cref="InvalidOperationException">路径为空时抛出。</exception>
|
||||
/// <exception cref="DirectoryNotFoundException">目录不存在时抛出。</exception>
|
||||
private static string NormalizeExistingDirectory(string? path)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(path))
|
||||
@@ -387,6 +421,12 @@ namespace FileShare_Services.Services.FileLibrary
|
||||
return new DirectoryInfo(fullPath).FullName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 解析根目录的显示名称,优先使用用户指定名称,否则使用目录名。
|
||||
/// </summary>
|
||||
/// <param name="path">目录路径。</param>
|
||||
/// <param name="displayName">用户指定的显示名称。</param>
|
||||
/// <returns>最终显示名称。</returns>
|
||||
private static string ResolveDisplayName(string path, string? displayName)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(displayName))
|
||||
@@ -398,11 +438,22 @@ namespace FileShare_Services.Services.FileLibrary
|
||||
return string.IsNullOrWhiteSpace(directory.Name) ? directory.FullName : directory.Name;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 规范化扫描间隔,限制在 1 到 1440 分钟范围内,未指定时使用默认值。
|
||||
/// </summary>
|
||||
/// <param name="interval">用户指定的间隔。</param>
|
||||
/// <returns>规范化后的间隔分钟数。</returns>
|
||||
private static int NormalizeInterval(int? interval)
|
||||
{
|
||||
return Math.Clamp(interval ?? DefaultScanIntervalMinutes, 1, 1440);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 安全获取驱动器属性值,驱动器未就绪或访问异常时返回 null。
|
||||
/// </summary>
|
||||
/// <param name="drive">驱动器信息。</param>
|
||||
/// <param name="selector">属性选择器。</param>
|
||||
/// <returns>属性值,不可用时返回 null。</returns>
|
||||
private static long? SafeDriveValue(DriveInfo drive, Func<DriveInfo, long> selector)
|
||||
{
|
||||
try
|
||||
@@ -415,6 +466,12 @@ namespace FileShare_Services.Services.FileLibrary
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将 <see cref="ManagedLibraryRoot"/> 实体映射为 <see cref="LibraryRootDto"/>。
|
||||
/// </summary>
|
||||
/// <param name="root">数据库实体。</param>
|
||||
/// <param name="fileCount">关联的文件记录数。</param>
|
||||
/// <returns>DTO 对象。</returns>
|
||||
private static LibraryRootDto ToRootDto(ManagedLibraryRoot root, int fileCount)
|
||||
{
|
||||
return new LibraryRootDto(
|
||||
@@ -430,6 +487,11 @@ namespace FileShare_Services.Services.FileLibrary
|
||||
fileCount);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将 <see cref="ManagedFileRecord"/> 实体映射为 <see cref="FileRecordDto"/>,并生成流式访问和文本预览 URL。
|
||||
/// </summary>
|
||||
/// <param name="file">数据库实体。</param>
|
||||
/// <returns>DTO 对象。</returns>
|
||||
private static FileRecordDto ToFileDto(ManagedFileRecord file)
|
||||
{
|
||||
return new FileRecordDto(
|
||||
|
||||
Reference in New Issue
Block a user