Initial commit

This commit is contained in:
shiyu
2025-05-18 20:48:20 +08:00
commit cde2c7b997
79 changed files with 5713 additions and 0 deletions

View File

@@ -0,0 +1,35 @@
namespace Foxel.Services.Interface;
public interface IAiService
{
/// <summary>
/// 分析图像并返回标题和描述
/// </summary>
/// <param name="base64Image">Base64格式的图像数据</param>
/// <returns>图像的标题和描述</returns>
Task<(string title, string description)> AnalyzeImageAsync(string base64Image);
/// <summary>
/// 基于描述匹配标签
/// </summary>
/// <param name="description">图片描述</param>
/// <param name="availableTags">可用标签列表</param>
/// <returns>匹配的标签名称列表</returns>
Task<List<string>> MatchTagsAsync(string description, List<string> availableTags);
/// <summary>
/// 直接从图像生成标签
/// </summary>
/// <param name="base64Image">Base64格式的图像数据</param>
/// <param name="availableTags">可用标签列表</param>
/// <param name="allowNewTags">是否允许生成新标签(不在availableTags中的标签)</param>
/// <returns>匹配的标签名称列表</returns>
Task<List<string>> GenerateTagsFromImageAsync(string base64Image, List<string> availableTags, bool allowNewTags = false);
/// <summary>
/// 获取文本的嵌入向量
/// </summary>
/// <param name="text">需要进行嵌入的文本</param>
/// <returns>表示文本语义的浮点数组向量</returns>
Task<float[]> GetEmbeddingAsync(string text);
}

View File

@@ -0,0 +1,17 @@
using Foxel.Models;
using Foxel.Models.Response;
using Foxel.Models.Response.Album;
namespace Foxel.Services.Interface;
public interface IAlbumService
{
Task<PaginatedResult<AlbumResponse>> GetAlbumsAsync(int page = 1, int pageSize = 10, int? userId = null);
Task<AlbumResponse> GetAlbumByIdAsync(int id);
Task<AlbumResponse> CreateAlbumAsync(string name, string? description, int userId);
Task<AlbumResponse> UpdateAlbumAsync(int id, string name, string? description, int? userId = null);
Task<bool> DeleteAlbumAsync(int id);
Task<bool> AddPictureToAlbumAsync(int albumId, int pictureId);
Task<bool> AddPicturesToAlbumAsync(int albumId, List<int> pictureIds);
Task<bool> RemovePictureFromAlbumAsync(int albumId, int pictureId);
}

View File

@@ -0,0 +1,51 @@
using Foxel.Models.DataBase;
namespace Foxel.Services.Interface;
/// <summary>
/// 后台任务队列接口
/// </summary>
public interface IBackgroundTaskQueue
{
/// <summary>
/// 将图片处理任务添加到队列
/// </summary>
/// <param name="pictureId">图片ID</param>
/// <param name="originalFilePath">原始图片路径</param>
/// <returns>任务ID</returns>
Task<Guid> QueuePictureProcessingTaskAsync(int pictureId, string originalFilePath);
/// <summary>
/// 获取用户的所有任务状态
/// </summary>
/// <param name="userId">用户ID</param>
/// <returns>该用户的任务状态列表</returns>
Task<List<PictureProcessingStatus>> GetUserTasksStatusAsync(int userId);
/// <summary>
/// 获取特定图片的处理状态
/// </summary>
/// <param name="pictureId">图片ID</param>
/// <returns>处理状态</returns>
Task<PictureProcessingStatus?> GetPictureProcessingStatusAsync(int pictureId);
/// <summary>
/// 恢复未完成的任务
/// </summary>
Task RestoreUnfinishedTasksAsync();
}
/// <summary>
/// 图片处理状态
/// </summary>
public class PictureProcessingStatus
{
public int PictureId { get; set; }
public Guid TaskId { get; set; }
public string PictureName { get; set; } = string.Empty;
public ProcessingStatus Status { get; set; }
public int Progress { get; set; } // 0-100
public string? Error { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime? CompletedAt { get; set; }
}

View File

@@ -0,0 +1,19 @@
using Foxel.Models.DataBase;
namespace Foxel.Services.Interface;
public interface IConfigService
{
string this[string key] { get; }
Task<string?> GetValueAsync(string key);
Task<T?> GetValueAsync<T>(string key, T? defaultValue = default);
Task<Config?> GetConfigAsync(string key);
Task<List<Config>> GetAllConfigsAsync();
Task<Config> SetConfigAsync(string key, string value, string? description = null);
Task<bool> DeleteConfigAsync(string key);
Task<bool> ExistsAsync(string key);
}

View File

@@ -0,0 +1,6 @@
namespace Foxel.Services.Interface;
public interface IDatabaseInitializer
{
Task InitializeAsync();
}

View File

@@ -0,0 +1,87 @@
using Foxel.Models;
using Foxel.Models.DataBase;
using Foxel.Models.Response.Picture;
namespace Foxel.Services.Interface;
public interface IPictureService
{
Task<PaginatedResult<PictureResponse>> GetPicturesAsync(
int page = 1,
int pageSize = 8,
string? searchQuery = null,
List<string>? tags = null,
DateTime? startDate = null,
DateTime? endDate = null,
int? userId = null,
string? sortBy = "newest",
bool? onlyWithGps = false,
bool useVectorSearch = false,
double similarityThreshold = 0.36,
int? excludeAlbumId = null,
int? albumId = null,
bool onlyFavorites = false,
int? ownerId = null,
bool includeAllPublic = false
);
Task<(PictureResponse Picture, int Id)> UploadPictureAsync(
string fileName,
Stream fileStream,
string contentType,
int? userId,
PermissionType permission = PermissionType.Public,
int? albumId = null,
StorageType storageType = StorageType.Telegram
);
Task<ExifInfo> GetPictureExifInfoAsync(int pictureId);
/// <summary>
/// 批量删除多张图片
/// </summary>
/// <param name="pictureIds">要删除的图片ID列表</param>
/// <returns>每个图片ID对应的删除结果、可能的错误信息和所有者ID</returns>
Task<Dictionary<int, (bool Success, string? ErrorMessage, int? UserId)>> DeleteMultiplePicturesAsync(
List<int> pictureIds);
/// <summary>
/// 更新图片信息
/// </summary>
/// <param name="pictureId">图片ID</param>
/// <param name="name">新标题(可选)</param>
/// <param name="description">新描述(可选)</param>
/// <param name="tags">新标签(可选)</param>
/// <returns>更新后的图片视图模型和所有者ID</returns>
Task<(PictureResponse Picture, int? UserId)> UpdatePictureAsync(
int pictureId,
string? name = null,
string? description = null,
List<string>? tags = null);
/// <summary>
/// 收藏图片
/// </summary>
/// <param name="pictureId">图片ID</param>
/// <param name="userId">用户ID</param>
/// <returns>成功/失败</returns>
Task<bool> FavoritePictureAsync(int pictureId, int userId);
/// <summary>
/// 取消收藏图片
/// </summary>
/// <param name="pictureId">图片ID</param>
/// <param name="userId">用户ID</param>
/// <returns>成功/失败</returns>
Task<bool> UnfavoritePictureAsync(int pictureId, int userId);
/// <summary>
/// 检查图片是否被特定用户收藏
/// </summary>
/// <param name="pictureId">图片ID</param>
/// <param name="userId">用户ID</param>
/// <returns>是否收藏</returns>
Task<bool> IsPictureFavoritedByUserAsync(int pictureId, int userId);
}

View File

@@ -0,0 +1,30 @@
namespace Foxel.Services.Interface;
public interface IStorageProvider
{
/// <summary>
/// 保存文件
/// </summary>
Task<string> SaveAsync(Stream fileStream, string fileName, string contentType);
/// <summary>
/// 删除文件
/// </summary>
Task DeleteAsync(string storagePath);
/// <summary>
/// 获取文件URL
/// </summary>
string GetUrl(string storagePath);
/// <summary>
/// 下载文件到本地临时目录
/// </summary>
/// <param name="storagePath">存储路径</param>
/// <returns>本地文件路径</returns>
Task<string> DownloadFileAsync(string storagePath)
{
// 默认实现 - 子类应重写此方法
throw new NotImplementedException("此存储提供者不支持下载文件功能");
}
}

View File

@@ -0,0 +1,14 @@
using Foxel.Models.DataBase;
using Foxel.Services.Interface;
namespace Foxel.Services.Interface;
public interface IStorageProviderFactory
{
/// <summary>
/// 根据存储类型获取对应的存储提供者
/// </summary>
/// <param name="storageType">存储类型</param>
/// <returns>存储提供者实例</returns>
IStorageProvider GetProvider(StorageType storageType);
}

View File

@@ -0,0 +1,24 @@
using Foxel.Models;
using Foxel.Models.Response.Tag;
namespace Foxel.Services.Interface;
public interface ITagService
{
Task<PaginatedResult<TagResponse>> GetFilteredTagsAsync(
int page = 1,
int pageSize = 20,
string? searchQuery = null,
string? sortBy = "pictureCount",
string? sortDirection = "desc",
int? minPictureCount = null
);
Task<TagResponse> GetTagByIdAsync(int id);
Task<TagResponse> CreateTagAsync(string name, string? description = null);
Task<TagResponse> UpdateTagAsync(int id, string? name = null, string? description = null);
Task<bool> DeleteTagAsync(int id);
}

View File

@@ -0,0 +1,15 @@
using Foxel.Models.DataBase;
using Foxel.Models.Request;
using Foxel.Models.Request.Auth;
namespace Foxel.Services.Interface;
public interface IUserService
{
Task<(bool success, string message, User? user)> RegisterUserAsync(RegisterRequest request);
Task<(bool success, string message, User? user)> AuthenticateUserAsync(LoginRequest request);
Task<string> GenerateJwtTokenAsync(User user);
Task<User?> GetUserByIdAsync(int userId);
Task<(bool success, string message, User? user)> FindOrCreateGitHubUserAsync(
string githubId, string githubLogin, string? email);
}