diff --git a/Api/Management/PictureManagementController.cs b/Api/Management/PictureManagementController.cs new file mode 100644 index 0000000..877538f --- /dev/null +++ b/Api/Management/PictureManagementController.cs @@ -0,0 +1,98 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Foxel.Models; +using Foxel.Models.Response.Picture; +using Foxel.Controllers; +using Foxel.Services.Management; + +namespace Foxel.Api.Management; + +[Authorize(Roles = "Administrator")] +[Route("api/management/picture")] +public class PictureManagementController(IPictureManagementService pictureManagementService) : BaseApiController +{ + [HttpGet("get_pictures")] + public async Task>> GetPictures( + [FromQuery] int page = 1, [FromQuery] int pageSize = 10) + { + try + { + var pictures = await pictureManagementService.GetPicturesAsync(page, pageSize); + return PaginatedSuccess(pictures.Data, pictures.TotalCount, pictures.Page, pictures.PageSize); + } + catch (Exception ex) + { + return PaginatedError($"获取图片列表失败: {ex.Message}", 500); + } + } + + [HttpGet("get_picture/{id}")] + public async Task>> GetPictureById(int id) + { + try + { + var picture = await pictureManagementService.GetPictureByIdAsync(id); + return Success(picture, "图片获取成功"); + } + catch (KeyNotFoundException) + { + return Error("找不到指定图片", 404); + } + catch (Exception ex) + { + return Error($"获取图片失败: {ex.Message}", 500); + } + } + + [HttpPost("delete_picture")] + public async Task>> DeletePicture([FromBody] int id) + { + try + { + var result = await pictureManagementService.DeletePictureAsync(id); + return Success(result, "图片删除成功"); + } + catch (KeyNotFoundException) + { + return Error("找不到要删除的图片", 404); + } + catch (Exception ex) + { + return Error($"删除图片失败: {ex.Message}", 500); + } + } + + [HttpPost("batch_delete_pictures")] + public async Task>> BatchDeletePictures([FromBody] List ids) + { + try + { + if (ids.Count == 0) + { + return Error("未提供图片ID"); + } + + var result = await pictureManagementService.BatchDeletePicturesAsync(ids); + return Success(result, $"成功删除 {result.SuccessCount} 张图片,失败 {result.FailedCount} 张"); + } + catch (Exception ex) + { + return Error($"批量删除图片失败: {ex.Message}", 500); + } + } + + [HttpGet("get_pictures_by_user/{userId}")] + public async Task>> GetPicturesByUserId( + int userId, [FromQuery] int page = 1, [FromQuery] int pageSize = 10) + { + try + { + var pictures = await pictureManagementService.GetPicturesByUserIdAsync(userId, page, pageSize); + return PaginatedSuccess(pictures.Data, pictures.TotalCount, pictures.Page, pictures.PageSize); + } + catch (Exception ex) + { + return PaginatedError($"获取用户图片列表失败: {ex.Message}", 500); + } + } +} diff --git a/Api/Management/SystemManageMentController.cs b/Api/Management/SystemManageMentController.cs new file mode 100644 index 0000000..c7a287e --- /dev/null +++ b/Api/Management/SystemManageMentController.cs @@ -0,0 +1,90 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Foxel.Controllers; +using Foxel.Models; +using Foxel.Services.VectorDB; + +namespace Foxel.Api.Management; + +[Authorize(Roles = "Administrator")] +[Route("api/management/system")] +public class SystemManagementController(IVectorDbService vectorDbService) : BaseApiController +{ + private readonly VectorDbManager _vectorDbManager = (VectorDbManager)vectorDbService; + + [HttpPost("vector-db/switch")] + public async Task>> SwitchVectorDb([FromBody] SwitchVectorDbRequest request) + { + try + { + // 将字符串转换为枚举类型(如果需要) + if (Enum.TryParse(request.Type, out var dbType)) + { + await _vectorDbManager.SwitchVectorDbAsync(dbType); + return Success(true, $"已切换到 {request.Type} 向量数据库"); + } + else + { + return Error($"无效的向量数据库类型: {request.Type}", 400); + } + } + catch (Exception ex) + { + return Error($"切换向量数据库失败: {ex.Message}", 500); + } + } + + [HttpGet("vector-db/current")] + public ActionResult> GetCurrentVectorDb() + { + try + { + var currentType = _vectorDbManager.GetCurrentVectorDbType(); + var info = new VectorDbInfo { Type = currentType.ToString() }; + return Success(info, "获取当前向量数据库类型成功"); + } + catch (Exception ex) + { + return Error($"获取当前向量数据库类型失败: {ex.Message}", 500); + } + } + + [HttpDelete("vector-db/clear")] + public async Task>> ClearVectors() + { + try + { + await _vectorDbManager.ClearVectorsAsync(); + return Success(true, "向量数据库清空成功"); + } + catch (Exception ex) + { + return Error($"清空向量数据库失败: {ex.Message}", 500); + } + } + + [HttpPost("vector-db/rebuild")] + public async Task>> RebuildVectors() + { + try + { + await _vectorDbManager.ClearVectorsAsync(); + _ = _vectorDbManager.BuildUserPictureVectorsAsync(); + return Success(true, "向量数据库重建中,请稍后检查状态"); + } + catch (Exception ex) + { + return Error($"重建向量数据库失败: {ex.Message}", 500); + } + } +} + +public class SwitchVectorDbRequest +{ + public string Type { get; set; } = string.Empty; +} + +public class VectorDbInfo +{ + public string Type { get; set; } = string.Empty; +} diff --git a/Api/Management/UserManagementController.cs b/Api/Management/UserManagementController.cs new file mode 100644 index 0000000..a02f85c --- /dev/null +++ b/Api/Management/UserManagementController.cs @@ -0,0 +1,124 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Foxel.Models; +using Foxel.Models.Request.User; +using Foxel.Models.Response.User; +using Foxel.Controllers; +using Foxel.Services.Management; + +namespace Foxel.Api.Management; + +[Authorize(Roles = "Administrator")] +[Route("api/management/user")] +public class UserManagementController(IUserManagementService userManagementService) : BaseApiController +{ + [HttpGet("get_users")] + public async Task>> GetUsers( + [FromQuery] int page = 1, [FromQuery] int pageSize = 10) + { + try + { + var users = await userManagementService.GetUsersAsync(page, pageSize); + return PaginatedSuccess(users.Data, users.TotalCount, users.Page, users.PageSize); + } + catch (Exception ex) + { + return PaginatedError($"获取用户列表失败: {ex.Message}", 500); + } + } + + [HttpGet("get_user/{id}")] + public async Task>> GetUserById(int id) + { + try + { + var user = await userManagementService.GetUserByIdAsync(id); + return Success(user, "用户获取成功"); + } + catch (KeyNotFoundException) + { + return Error("找不到指定用户", 404); + } + catch (Exception ex) + { + return Error($"获取用户失败: {ex.Message}", 500); + } + } + + [HttpPost("create_user")] + public async Task>> CreateUser([FromBody] CreateUserRequest request) + { + try + { + var user = await userManagementService.CreateUserAsync(request.UserName, request.Email, request.Password, request.Role); + return Success(user, "用户创建成功"); + } + catch (ArgumentException ex) + { + return Error(ex.Message); + } + catch (Exception ex) + { + return Error($"创建用户失败: {ex.Message}", 500); + } + } + + [HttpPost("update_user")] + public async Task>> UpdateUser([FromBody] UpdateUserRequest request) + { + try + { + var user = await userManagementService.UpdateUserAsync(request.Id, request.UserName, request.Email, request.Role); + return Success(user, "用户更新成功"); + } + catch (KeyNotFoundException) + { + return Error("找不到要更新的用户", 404); + } + catch (ArgumentException ex) + { + return Error(ex.Message); + } + catch (Exception ex) + { + return Error($"更新用户失败: {ex.Message}", 500); + } + } + + [HttpPost("delete_user")] + public async Task>> DeleteUser([FromBody] int id) + { + try + { + var result = await userManagementService.DeleteUserAsync(id); + return Success(result, "用户删除成功"); + } + catch (KeyNotFoundException) + { + return Error("找不到要删除的用户", 404); + } + catch (Exception ex) + { + return Error($"删除用户失败: {ex.Message}", 500); + } + } + + [HttpPost("batch_delete_users")] + public async Task>> BatchDeleteUsers([FromBody] List ids) + { + try + { + if (ids.Count == 0) + { + return Error("未提供用户ID"); + } + + var result = await userManagementService.BatchDeleteUsersAsync(ids); + return Success(result, $"成功删除 {result.SuccessCount} 个用户,失败 {result.FailedCount} 个"); + } + catch (Exception ex) + { + return Error($"批量删除用户失败: {ex.Message}", 500); + } + } +} \ No newline at end of file diff --git a/Extensions/ApplicationBuilderExtensions.cs b/Extensions/ApplicationBuilderExtensions.cs index 8f85cba..841fe38 100644 --- a/Extensions/ApplicationBuilderExtensions.cs +++ b/Extensions/ApplicationBuilderExtensions.cs @@ -23,5 +23,6 @@ public static class ApplicationBuilderExtensions public static void UseApplicationOpenApi(this WebApplication app) { app.MapOpenApi(); + app.MapScalarApiReference(); } } \ No newline at end of file diff --git a/Extensions/ServiceCollectionExtensions.cs b/Extensions/ServiceCollectionExtensions.cs index 9d91190..0bfdb50 100644 --- a/Extensions/ServiceCollectionExtensions.cs +++ b/Extensions/ServiceCollectionExtensions.cs @@ -9,9 +9,11 @@ using Foxel.Services.Auth; using Foxel.Services.Background; using Foxel.Services.Configuration; using Foxel.Services.Initializer; +using Foxel.Services.Management; using Foxel.Services.Media; using Foxel.Services.Storage; using Foxel.Services.Storage.Providers; +using Foxel.Services.VectorDB; namespace Foxel.Extensions; @@ -25,6 +27,8 @@ public static class ServiceCollectionExtensions services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); services.AddSingleton(); services.AddHostedService(); services.AddSingleton(); @@ -97,4 +101,11 @@ public static class ServiceCollectionExtensions policy => { policy.WithOrigins().AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod(); }); }); } + + public static void AddVectorDbServices(this IServiceCollection services) + { + services.AddSingleton(); + services.AddSingleton(provider => + provider.GetRequiredService()); + } } \ No newline at end of file diff --git a/Foxel.csproj b/Foxel.csproj index 654a441..5ea75da 100644 --- a/Foxel.csproj +++ b/Foxel.csproj @@ -8,7 +8,7 @@ - + @@ -17,6 +17,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/Models/Request/User/UserRequests.cs b/Models/Request/User/UserRequests.cs new file mode 100644 index 0000000..80cfdd6 --- /dev/null +++ b/Models/Request/User/UserRequests.cs @@ -0,0 +1,36 @@ +using System.ComponentModel.DataAnnotations; + +namespace Foxel.Models.Request.User; + +public class CreateUserRequest +{ + [Required(ErrorMessage = "用户名不能为空")] + public string UserName { get; set; } + + [Required(ErrorMessage = "邮箱不能为空")] + [EmailAddress(ErrorMessage = "邮箱格式不正确")] + public string Email { get; set; } + + [Required(ErrorMessage = "密码不能为空")] + [MinLength(6, ErrorMessage = "密码长度不能少于6个字符")] + public string Password { get; set; } + + [Required(ErrorMessage = "角色不能为空")] + public string Role { get; set; } = "User"; +} + +public class UpdateUserRequest +{ + [Required] + public int Id { get; set; } + + [Required(ErrorMessage = "用户名不能为空")] + public string UserName { get; set; } + + [Required(ErrorMessage = "邮箱不能为空")] + [EmailAddress(ErrorMessage = "邮箱格式不正确")] + public string Email { get; set; } + + [Required(ErrorMessage = "角色不能为空")] + public string Role { get; set; } +} diff --git a/Models/Response/User/UserResponse.cs b/Models/Response/User/UserResponse.cs new file mode 100644 index 0000000..90ea9fc --- /dev/null +++ b/Models/Response/User/UserResponse.cs @@ -0,0 +1,10 @@ +namespace Foxel.Models.Response.User; + +public class UserResponse +{ + public int Id { get; set; } + public string UserName { get; set; } + public string Email { get; set; } + public string Role { get; set; } + public DateTime CreatedAt { get; set; } +} diff --git a/Models/Vector/PictureVector.cs b/Models/Vector/PictureVector.cs index 61d4e7a..c5ca195 100644 --- a/Models/Vector/PictureVector.cs +++ b/Models/Vector/PictureVector.cs @@ -4,7 +4,7 @@ using Microsoft.Extensions.VectorData; public class PictureVector { - [VectorStoreKey] public int Id { get; set; } + [VectorStoreKey] public ulong Id { get; set; } [VectorStoreData] public string? Name { get; set; } [VectorStoreVector(Dimensions: 1024, DistanceFunction = DistanceFunction.CosineSimilarity)] diff --git a/Program.cs b/Program.cs index 1f078ca..7c969fc 100644 --- a/Program.cs +++ b/Program.cs @@ -16,7 +16,8 @@ builder.Services.AddHttpContextAccessor(); builder.Services.AddApplicationAuthentication(); builder.Services.AddApplicationAuthorization(); builder.Services.AddApplicationCors(); -builder.Services.AddSingleton(); +builder.Services.AddVectorDbServices(); +builder.Services.AddHostedService(); builder.Services.Configure(options => { options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto; diff --git a/Services/Auth/AuthService.cs b/Services/Auth/AuthService.cs index 7b8c6eb..c6c9327 100644 --- a/Services/Auth/AuthService.cs +++ b/Services/Auth/AuthService.cs @@ -33,12 +33,14 @@ public class AuthService(IDbContextFactory dbContextFactory, IConfi Email = request.Email, PasswordHash = HashPassword(request.Password), CreatedAt = DateTime.UtcNow, - UpdatedAt = DateTime.UtcNow + UpdatedAt = DateTime.UtcNow, + RoleId = 2, + Role = null, }; var userCount = await context.Users.CountAsync(); if (userCount == 0) { - var role = await context.Roles.FirstOrDefaultAsync(r => r.Id == 1); + var role = await context.Roles.FirstOrDefaultAsync(r => r.Name == "Administrator"); user.RoleId = 1; user.Role = role; } diff --git a/Services/Background/BackgroundTaskQueue.cs b/Services/Background/BackgroundTaskQueue.cs index 5037402..c4fe9bc 100644 --- a/Services/Background/BackgroundTaskQueue.cs +++ b/Services/Background/BackgroundTaskQueue.cs @@ -5,6 +5,7 @@ using Foxel.Services.AI; using Foxel.Services.Attributes; using Foxel.Services.Configuration; using Foxel.Services.Storage; +using Foxel.Services.VectorDB; using Foxel.Utils; using Microsoft.EntityFrameworkCore; @@ -32,7 +33,7 @@ public sealed class BackgroundTaskQueue : IBackgroundTaskQueue, IDisposable _activeTasks = new ConcurrentDictionary(); _pictureStatus = new ConcurrentDictionary(); _processingTasks = new List(); - _maxConcurrentTasks = configuration.GetValueAsync("BackgroundTasks:MaxConcurrentTasks", 4).Result; + _maxConcurrentTasks = configuration.GetValueAsync("BackgroundTasks:MaxConcurrentTasks", 10).Result; _signal = new SemaphoreSlim(_maxConcurrentTasks); var options = new BoundedChannelOptions(10000) { @@ -304,10 +305,10 @@ public sealed class BackgroundTaskQueue : IBackgroundTaskQueue, IDisposable picture.Embedding = embedding; if (picture.UserId.HasValue && embedding.Length > 0) { - var vectorDbService = scope.ServiceProvider.GetRequiredService(); - var pictureVector = new Foxel.Models.Vector.PictureVector + var vectorDbService = scope.ServiceProvider.GetRequiredService(); + var pictureVector = new Models.Vector.PictureVector { - Id = picture.Id, + Id = (ulong)picture.Id, Name = picture.Name, Embedding = embedding }; diff --git a/Services/Initializer/DatabaseInitializer.cs b/Services/Initializer/DatabaseInitializer.cs index cfdff2d..17cd89d 100644 --- a/Services/Initializer/DatabaseInitializer.cs +++ b/Services/Initializer/DatabaseInitializer.cs @@ -72,6 +72,12 @@ public class DatabaseInitializer( await EnsureConfigExistsAsync(key, value); } + // 确保向量数据库配置存在 + if (!await configService.ExistsAsync("VectorDb:Type")) + { + await configService.SetConfigAsync("VectorDb:Type", "InMemory", "向量数据库类型"); + } + // 初始化管理员角色和用户 await InitializeAdminRoleAndUserAsync(); @@ -128,6 +134,22 @@ public class DatabaseInitializer( await context.SaveChangesAsync(); } + // 检查并创建用户角色 + var userRole = await context.Roles.FirstOrDefaultAsync(r => r.Name == "User"); + if (userRole == null) + { + logger.LogInformation("创建用户角色"); + userRole = new Role + { + Name = "User", + Description = "普通用户角色", + CreatedAt = DateTime.UtcNow, + UpdatedAt = DateTime.UtcNow + }; + await context.Roles.AddAsync(userRole); + await context.SaveChangesAsync(); + } + logger.LogInformation("请注意,第一个注册的用户将自动成为管理员"); } } \ No newline at end of file diff --git a/Services/Management/IPictureManagementService.cs b/Services/Management/IPictureManagementService.cs new file mode 100644 index 0000000..e102642 --- /dev/null +++ b/Services/Management/IPictureManagementService.cs @@ -0,0 +1,13 @@ +using Foxel.Models; +using Foxel.Models.Response.Picture; + +namespace Foxel.Services.Management; + +public interface IPictureManagementService +{ + Task> GetPicturesAsync(int page = 1, int pageSize = 10); + Task GetPictureByIdAsync(int id); + Task DeletePictureAsync(int id); + Task BatchDeletePicturesAsync(List ids); + Task> GetPicturesByUserIdAsync(int userId, int page = 1, int pageSize = 10); +} diff --git a/Services/Management/IUserManagementService.cs b/Services/Management/IUserManagementService.cs new file mode 100644 index 0000000..47af034 --- /dev/null +++ b/Services/Management/IUserManagementService.cs @@ -0,0 +1,21 @@ +using Foxel.Models; +using Foxel.Models.Response.User; + +namespace Foxel.Services.Management; + +public interface IUserManagementService +{ + Task> GetUsersAsync(int page = 1, int pageSize = 10); + Task GetUserByIdAsync(int id); + Task CreateUserAsync(string userName, string email, string password, string role); + Task UpdateUserAsync(int id, string userName, string email, string role); + Task DeleteUserAsync(int id); + Task BatchDeleteUsersAsync(List ids); +} + +public class BatchDeleteResult +{ + public int SuccessCount { get; set; } + public int FailedCount { get; set; } + public List FailedIds { get; set; } = new(); +} diff --git a/Services/Management/PictureManagementService.cs b/Services/Management/PictureManagementService.cs new file mode 100644 index 0000000..a63820a --- /dev/null +++ b/Services/Management/PictureManagementService.cs @@ -0,0 +1,218 @@ +using Foxel.Models; +using Foxel.Models.Response.Picture; +using Foxel.Services.Configuration; +using Foxel.Services.Storage; +using Microsoft.EntityFrameworkCore; + +namespace Foxel.Services.Management; + +public class PictureManagementService( + IDbContextFactory contextFactory, + IStorageService storageService) : IPictureManagementService +{ + public async Task> GetPicturesAsync(int page = 1, int pageSize = 10) + { + if (page < 1) page = 1; + if (pageSize < 1) pageSize = 10; + + await using var dbContext = await contextFactory.CreateDbContextAsync(); + + // 构建查询 + var query = dbContext.Pictures + .Include(p => p.User) + .OrderByDescending(p => p.CreatedAt); + + // 获取总数和分页数据 + var totalCount = await query.CountAsync(); + var pictures = await query + .Skip((page - 1) * pageSize) + .Take(pageSize) + .ToListAsync(); + + // 转换为响应模型 + var pictureResponses = pictures.Select(picture => new PictureResponse + { + Id = picture.Id, + Name = picture.Name, + Path = storageService.ExecuteAsync(picture.StorageType, provider => + Task.FromResult(provider.GetUrl(picture.Path ?? string.Empty))).Result, + ThumbnailPath = storageService.ExecuteAsync(picture.StorageType, provider => + Task.FromResult(provider.GetUrl(picture.ThumbnailPath ?? string.Empty))).Result, + Description = picture.Description, + CreatedAt = picture.CreatedAt, + TakenAt = picture.TakenAt, + ExifInfo = picture.ExifInfo, + UserId = picture.UserId, + Username = picture.User?.UserName, + Tags = picture.Tags?.Select(t => t.Name).ToList(), + AlbumId = picture.AlbumId, + AlbumName = picture.Album?.Name, + Permission = picture.Permission, + FavoriteCount = picture.Favorites?.Count ?? 0, + }).ToList(); + + return new PaginatedResult + { + Data = pictureResponses, + Page = page, + PageSize = pageSize, + TotalCount = totalCount + }; + } + + public async Task GetPictureByIdAsync(int id) + { + await using var dbContext = await contextFactory.CreateDbContextAsync(); + + var picture = await dbContext.Pictures + .Include(p => p.User) + .FirstOrDefaultAsync(p => p.Id == id); + + if (picture == null) + throw new KeyNotFoundException($"找不到ID为{id}的图片"); + + return new PictureResponse + { + Id = picture.Id, + Name = picture.Name, + Path = picture.Path, + ThumbnailPath = picture.ThumbnailPath, + Description = picture.Description, + CreatedAt = picture.CreatedAt, + TakenAt = picture.TakenAt, + ExifInfo = picture.ExifInfo, + UserId = picture.UserId, + Username = picture.User?.UserName, + Tags = picture.Tags?.Select(t => t.Name).ToList(), + AlbumId = picture.AlbumId, + AlbumName = picture.Album?.Name, + Permission = picture.Permission, + ProcessingStatus = picture.ProcessingStatus, + ProcessingError = picture.ProcessingError, + ProcessingProgress = picture.ProcessingProgress, + FavoriteCount = picture.Favorites?.Count ?? 0, + IsFavorited = false + }; + } + + public async Task DeletePictureAsync(int id) + { + await using var dbContext = await contextFactory.CreateDbContextAsync(); + + var picture = await dbContext.Pictures.FindAsync(id); + + if (picture == null) + throw new KeyNotFoundException($"找不到ID为{id}的图片"); + + // 保存文件路径信息用于后续删除 + var filePath = picture.Path; + var thumbnailPath = picture.ThumbnailPath; + var storageType = picture.StorageType; + + // 删除数据库记录 + dbContext.Pictures.Remove(picture); + await dbContext.SaveChangesAsync(); + + // 删除物理文件 + try + { + if (!string.IsNullOrEmpty(filePath)) + { + await storageService.ExecuteAsync(storageType, + provider => provider.DeleteAsync(filePath)); + } + if (!string.IsNullOrEmpty(thumbnailPath)) + { + await storageService.ExecuteAsync(storageType, + provider => provider.DeleteAsync(thumbnailPath)); + } + } + catch (Exception ex) + { + Console.WriteLine($"删除图片文件时出错:{ex.Message}"); + } + return true; + } + + public async Task BatchDeletePicturesAsync(List ids) + { + var result = new BatchDeleteResult(); + + foreach (var id in ids) + { + try + { + var success = await DeletePictureAsync(id); + if (success) + { + result.SuccessCount++; + } + else + { + result.FailedCount++; + result.FailedIds.Add(id); + } + } + catch + { + result.FailedCount++; + result.FailedIds.Add(id); + } + } + + return result; + } + + public async Task> GetPicturesByUserIdAsync(int userId, int page = 1, int pageSize = 10) + { + if (page < 1) page = 1; + if (pageSize < 1) pageSize = 10; + + await using var dbContext = await contextFactory.CreateDbContextAsync(); + + // 构建查询 + var query = dbContext.Pictures + .Include(p => p.User) + .Where(p => p.UserId == userId) + .OrderByDescending(p => p.CreatedAt); + + // 获取总数和分页数据 + var totalCount = await query.CountAsync(); + var pictures = await query + .Skip((page - 1) * pageSize) + .Take(pageSize) + .ToListAsync(); + + // 转换为响应模型 + var pictureResponses = pictures.Select(picture => new PictureResponse + { + Id = picture.Id, + Name = picture.Name, + Path = picture.Path, + ThumbnailPath = picture.ThumbnailPath, + Description = picture.Description, + CreatedAt = picture.CreatedAt, + TakenAt = picture.TakenAt, + ExifInfo = picture.ExifInfo, + UserId = picture.UserId, + Username = picture.User?.UserName, + Tags = picture.Tags?.Select(t => t.Name).ToList(), + AlbumId = picture.AlbumId, + AlbumName = picture.Album?.Name, + Permission = picture.Permission, + ProcessingStatus = picture.ProcessingStatus, + ProcessingError = picture.ProcessingError, + ProcessingProgress = picture.ProcessingProgress, + FavoriteCount = picture.Favorites?.Count ?? 0, + IsFavorited = false + }).ToList(); + + return new PaginatedResult + { + Data = pictureResponses, + Page = page, + PageSize = pageSize, + TotalCount = totalCount + }; + } +} diff --git a/Services/Management/UserManagementService.cs b/Services/Management/UserManagementService.cs new file mode 100644 index 0000000..150d15a --- /dev/null +++ b/Services/Management/UserManagementService.cs @@ -0,0 +1,226 @@ +using System.Security.Cryptography; +using System.Text; +using Foxel.Models; +using Foxel.Models.Response.User; +using Microsoft.EntityFrameworkCore; + +namespace Foxel.Services.Management; + +public class UserManagementService( + IDbContextFactory contextFactory) : IUserManagementService +{ + public async Task> GetUsersAsync(int page = 1, int pageSize = 10) + { + if (page < 1) page = 1; + if (pageSize < 1) pageSize = 10; + + await using var dbContext = await contextFactory.CreateDbContextAsync(); + + // 构建查询 + var query = dbContext.Users + .Include(u => u.Role) + .OrderByDescending(u => u.CreatedAt); + + // 获取总数和分页数据 + var totalCount = await query.CountAsync(); + var users = await query + .Skip((page - 1) * pageSize) + .Take(pageSize) + .ToListAsync(); + + // 转换为响应模型 + var userResponses = users.Select(user => new UserResponse + { + Id = user.Id, + UserName = user.UserName, + Email = user.Email, + Role = user.Role?.Name ?? "User", + CreatedAt = user.CreatedAt, + }).ToList(); + + return new PaginatedResult + { + Data = userResponses, + Page = page, + PageSize = pageSize, + TotalCount = totalCount + }; + } + + public async Task GetUserByIdAsync(int id) + { + await using var dbContext = await contextFactory.CreateDbContextAsync(); + + var user = await dbContext.Users + .Include(u => u.Role) + .FirstOrDefaultAsync(u => u.Id == id); + + if (user == null) + throw new KeyNotFoundException($"找不到ID为{id}的用户"); + + return new UserResponse + { + Id = user.Id, + UserName = user.UserName, + Email = user.Email, + Role = user.Role?.Name ?? "User", + CreatedAt = user.CreatedAt, + }; + } + + public async Task CreateUserAsync(string userName, string email, string password, string roleName) + { + if (string.IsNullOrWhiteSpace(userName)) + throw new ArgumentException("用户名不能为空", nameof(userName)); + + if (string.IsNullOrWhiteSpace(email)) + throw new ArgumentException("邮箱不能为空", nameof(email)); + + if (string.IsNullOrWhiteSpace(password)) + throw new ArgumentException("密码不能为空", nameof(password)); + + await using var dbContext = await contextFactory.CreateDbContextAsync(); + + // 检查角色是否存在 + var role = await dbContext.Roles.FirstOrDefaultAsync(r => r.Name == roleName); + if (role == null) + throw new ArgumentException($"角色 '{roleName}' 不存在", nameof(roleName)); + + // 检查用户名是否已存在 + if (await dbContext.Users.AnyAsync(u => u.UserName == userName)) + throw new ArgumentException($"用户名 '{userName}' 已被使用", nameof(userName)); + + // 检查邮箱是否已存在 + if (await dbContext.Users.AnyAsync(u => u.Email == email)) + throw new ArgumentException($"邮箱 '{email}' 已被使用", nameof(email)); + + // 生成密码哈希 + string passwordHash = HashPassword(password); + + // 创建新用户 + var user = new Models.DataBase.User + { + UserName = userName, + Email = email, + PasswordHash = passwordHash, + RoleId = role.Id, + Role = role, + CreatedAt = DateTime.UtcNow, + UpdatedAt = DateTime.UtcNow + }; + + // 添加用户 + dbContext.Users.Add(user); + await dbContext.SaveChangesAsync(); + + return new UserResponse + { + Id = user.Id, + UserName = user.UserName, + Email = user.Email, + Role = roleName, + CreatedAt = user.CreatedAt, + }; + } + + public async Task UpdateUserAsync(int id, string userName, string email, string roleName) + { + await using var dbContext = await contextFactory.CreateDbContextAsync(); + + var user = await dbContext.Users + .Include(u => u.Role) + .FirstOrDefaultAsync(u => u.Id == id); + + if (user == null) + throw new KeyNotFoundException($"找不到ID为{id}的用户"); + + if (string.IsNullOrWhiteSpace(userName)) + throw new ArgumentException("用户名不能为空", nameof(userName)); + + if (string.IsNullOrWhiteSpace(email)) + throw new ArgumentException("邮箱不能为空", nameof(email)); + + // 检查角色是否存在 + var role = await dbContext.Roles.FirstOrDefaultAsync(r => r.Name == roleName); + if (role == null) + throw new ArgumentException($"角色 '{roleName}' 不存在", nameof(roleName)); + + // 检查邮箱是否已被其他用户使用 + var existingUserByEmail = await dbContext.Users.FirstOrDefaultAsync(u => u.Email == email && u.Id != id); + if (existingUserByEmail != null) + throw new ArgumentException($"邮箱 '{email}' 已被使用", nameof(email)); + + // 更新用户信息 + user.UserName = userName; + user.Email = email; + user.RoleId = role.Id; + user.Role = role; + user.UpdatedAt = DateTime.UtcNow; + + // 保存用户更改 + await dbContext.SaveChangesAsync(); + + return new UserResponse + { + Id = user.Id, + UserName = user.UserName, + Email = user.Email, + Role = role.Name, + CreatedAt = user.CreatedAt, + }; + } + + public async Task DeleteUserAsync(int id) + { + await using var dbContext = await contextFactory.CreateDbContextAsync(); + + var user = await dbContext.Users.FindAsync(id); + + if (user == null) + throw new KeyNotFoundException($"找不到ID为{id}的用户"); + + // 删除用户 + dbContext.Users.Remove(user); + + await dbContext.SaveChangesAsync(); + + return true; + } + + public async Task BatchDeleteUsersAsync(List ids) + { + var result = new BatchDeleteResult(); + + foreach (var id in ids) + { + try + { + var success = await DeleteUserAsync(id); + if (success) + { + result.SuccessCount++; + } + else + { + result.FailedCount++; + result.FailedIds.Add(id); + } + } + catch + { + result.FailedCount++; + result.FailedIds.Add(id); + } + } + + return result; + } + + // 辅助方法:生成密码哈希 + private string HashPassword(string password) + { + using var sha256 = SHA256.Create(); + var hashedBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(password)); + return Convert.ToBase64String(hashedBytes); + } +} \ No newline at end of file diff --git a/Services/Media/PictureService.cs b/Services/Media/PictureService.cs index 07ed9cb..e9f1d7f 100644 --- a/Services/Media/PictureService.cs +++ b/Services/Media/PictureService.cs @@ -19,7 +19,7 @@ public class PictureService( IAiService embeddingService, IConfigService configuration, IBackgroundTaskQueue backgroundTaskQueue, - VectorDbService vectorDbService, + IVectorDbService vectorDbService, IStorageService storageService) : IPictureService { @@ -102,10 +102,10 @@ public class PictureService( var picturesData = await dbContext.Pictures .Include(p => p.Tags) .Include(p => p.User) - .Where(p => ids.Contains(p.Id)) + .Where(p => ids.Contains((ulong)p.Id)) .ToListAsync(); var picturesOrdered = ids - .Select(id => picturesData.FirstOrDefault(p => p.Id == id)) + .Select(id => picturesData.FirstOrDefault(p => p.Id == (int)id)) .Where(p => p != null) .ToList(); var paginatedResults = picturesOrdered diff --git a/Services/VectorDb/IVectorDbService.cs b/Services/VectorDb/IVectorDbService.cs new file mode 100644 index 0000000..d808fe4 --- /dev/null +++ b/Services/VectorDb/IVectorDbService.cs @@ -0,0 +1,18 @@ +using Foxel.Models.Vector; + +namespace Foxel.Services.VectorDB; + +public interface IVectorDbService +{ + Task BuildUserPictureVectorsAsync(); + Task> SearchAsync(ReadOnlyMemory query, int? userId, int topK = 10); + Task AddPictureToUserCollectionAsync(int userId, PictureVector pictureVector); + Task RemovePictureFromUserCollectionAsync(int userId, int pictureId); + Task ClearVectorsAsync(); +} + +public enum VectorDbType +{ + InMemory, + Qdrant +} \ No newline at end of file diff --git a/Services/VectorDb/VectorDbService.cs b/Services/VectorDb/InMemoryVectorDbService.cs similarity index 68% rename from Services/VectorDb/VectorDbService.cs rename to Services/VectorDb/InMemoryVectorDbService.cs index e897ca5..f43782b 100644 --- a/Services/VectorDb/VectorDbService.cs +++ b/Services/VectorDb/InMemoryVectorDbService.cs @@ -5,19 +5,18 @@ using Microsoft.SemanticKernel.Connectors.InMemory; namespace Foxel.Services.VectorDB; -public class VectorDbService +public class InMemoryVectorDbService : IVectorDbService { private readonly VectorStore _vectorStore; private readonly IDbContextFactory _contextFactory; - public VectorDbService(IDbContextFactory contextFactory) + public InMemoryVectorDbService(IDbContextFactory contextFactory) { _vectorStore = new InMemoryVectorStore(); _contextFactory = contextFactory; - _ = InitData(); } - private async Task InitData() + public async Task BuildUserPictureVectorsAsync() { await using var dbContext = await _contextFactory.CreateDbContextAsync(); var userPictures = dbContext.Pictures @@ -30,12 +29,12 @@ public class VectorDbService { int userId = group.Key; var collectionName = $"picture_{userId}"; - var collection = _vectorStore.GetCollection(collectionName); + var collection = _vectorStore.GetCollection(collectionName); await collection.EnsureCollectionExistsAsync(); var picVectors = group.Select(p => new PictureVector { - Id = p.Id, + Id = (ulong)p.Id, Name = p.Name, Embedding = p.Embedding }).ToList(); @@ -50,7 +49,7 @@ public class VectorDbService public async Task> SearchAsync(ReadOnlyMemory query, int? userId, int topK = 10) { var collectionName = $"picture_{userId}"; - var collection = _vectorStore.GetCollection(collectionName); + var collection = _vectorStore.GetCollection(collectionName); var results = collection.SearchAsync(query, topK); var res = new List(); await foreach (var record in results) @@ -64,7 +63,7 @@ public class VectorDbService public async Task AddPictureToUserCollectionAsync(int userId, PictureVector pictureVector) { var collectionName = $"picture_{userId}"; - var collection = _vectorStore.GetCollection(collectionName); + var collection = _vectorStore.GetCollection(collectionName); await collection.EnsureCollectionExistsAsync(); await collection.UpsertAsync(pictureVector); } @@ -72,8 +71,18 @@ public class VectorDbService public async Task RemovePictureFromUserCollectionAsync(int userId, int pictureId) { var collectionName = $"picture_{userId}"; - var collection = _vectorStore.GetCollection(collectionName); + var collection = _vectorStore.GetCollection(collectionName); await collection.EnsureCollectionExistsAsync(); - await collection.DeleteAsync(pictureId); + await collection.DeleteAsync((ulong)pictureId); + } + + public async Task ClearVectorsAsync() + { + var collections = _vectorStore.ListCollectionNamesAsync(); + await foreach (var name in collections) + { + var collection = _vectorStore.GetCollection(name); + await collection.EnsureCollectionDeletedAsync(); + } } } \ No newline at end of file diff --git a/Services/VectorDb/QdrantVectorDbService.cs b/Services/VectorDb/QdrantVectorDbService.cs new file mode 100644 index 0000000..d9ed5f0 --- /dev/null +++ b/Services/VectorDb/QdrantVectorDbService.cs @@ -0,0 +1,112 @@ +using Foxel.Models.Vector; +using Foxel.Services.Configuration; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.VectorData; +using Microsoft.SemanticKernel.Connectors.Qdrant; +using Qdrant.Client; + +namespace Foxel.Services.VectorDB; + +public class QdrantVectorDbService : IVectorDbService +{ + private readonly IDbContextFactory _contextFactory; + private readonly IConfigService _configService; + private VectorStore? _vectorStore; + private string? _currentHost; + private string? _currentApiKey; + + public QdrantVectorDbService(IDbContextFactory contextFactory, IConfigService configService) + { + _contextFactory = contextFactory; + _configService = configService; + } + + private VectorStore GetVectorStore() + { + string host = _configService["VectorDb:QdrantHost"] ?? + "b63da3b8-c126-4546-95ab-176f907fb1ef.eu-central-1-0.aws.cloud.qdrant.io"; + + string apiKey = _configService["VectorDb:QdrantApiKey"] ?? + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3MiOiJtIn0.QzQN4cyo5mldCi9ohe0Aqap4fpTMuSEMGkXtkgBTNQI"; + + if (_vectorStore == null || _currentHost != host || _currentApiKey != apiKey) + { + var qdrantClient = new QdrantClient(host, https: true, apiKey: apiKey); + _vectorStore = new QdrantVectorStore(qdrantClient, true); + + _currentHost = host; + _currentApiKey = apiKey; + } + + return _vectorStore; + } + + public async Task BuildUserPictureVectorsAsync() + { + await using var dbContext = await _contextFactory.CreateDbContextAsync(); + var userPictures = dbContext.Pictures + .Where(p => p.UserId != null && p.Embedding != null) + .Select(p => new { p.Id, p.Name, p.Embedding, p.UserId }) + .GroupBy(p => p.UserId!.Value) + .ToList(); + + foreach (var group in userPictures) + { + int userId = group.Key; + var collectionName = $"picture_{userId}"; + var collection = GetVectorStore().GetCollection(collectionName); + await collection.EnsureCollectionExistsAsync(); + var picVectors = group.Select(p => new PictureVector + { + Id = (ulong)p.Id, + Name = p.Name, + Embedding = p.Embedding + }).ToList(); + + foreach (var picVector in picVectors) + { + await collection.UpsertAsync(picVector); + } + } + } + + public async Task> SearchAsync(ReadOnlyMemory query, int? userId, int topK = 10) + { + var collectionName = $"picture_{userId}"; + var collection = GetVectorStore().GetCollection(collectionName); + var results = collection.SearchAsync(query, topK); + var res = new List(); + await foreach (var record in results) + { + res.Add(record.Record); + } + + return res; + } + + public async Task AddPictureToUserCollectionAsync(int userId, PictureVector pictureVector) + { + var collectionName = $"picture_{userId}"; + var collection = GetVectorStore().GetCollection(collectionName); + await collection.EnsureCollectionExistsAsync(); + await collection.UpsertAsync(pictureVector); + } + + public async Task RemovePictureFromUserCollectionAsync(int userId, int pictureId) + { + var collectionName = $"picture_{userId}"; + var collection = GetVectorStore().GetCollection(collectionName); + await collection.EnsureCollectionExistsAsync(); + await collection.DeleteAsync((ulong)pictureId); + } + + public async Task ClearVectorsAsync() + { + var collections = GetVectorStore().ListCollectionNamesAsync(); + await foreach (var name in collections) + { + var collection = GetVectorStore().GetCollection(name); + await collection.EnsureCollectionDeletedAsync(); + } + } +} \ No newline at end of file diff --git a/Services/VectorDb/VectorDbInitializer.cs b/Services/VectorDb/VectorDbInitializer.cs new file mode 100644 index 0000000..7efd1f7 --- /dev/null +++ b/Services/VectorDb/VectorDbInitializer.cs @@ -0,0 +1,30 @@ +using Foxel.Services.Configuration; + +namespace Foxel.Services.VectorDB; + +public class VectorDbInitializer : IHostedService +{ + private readonly IVectorDbService _vectorDbService; + private readonly IConfigService _configService; + private const string VectorDbTypeConfigKey = "VectorDb:Type"; + + public VectorDbInitializer(IVectorDbService vectorDbService, IConfigService configService) + { + _vectorDbService = vectorDbService; + _configService = configService; + } + + public async Task StartAsync(CancellationToken cancellationToken) + { + var dbTypeStr = await _configService.GetValueAsync(VectorDbTypeConfigKey) ?? "InMemory"; + if (string.Equals(dbTypeStr, "InMemory", StringComparison.OrdinalIgnoreCase)) + { + await _vectorDbService.BuildUserPictureVectorsAsync(); + } + } + + public Task StopAsync(CancellationToken cancellationToken) + { + return Task.CompletedTask; + } +} diff --git a/Services/VectorDb/VectorDbManager.cs b/Services/VectorDb/VectorDbManager.cs new file mode 100644 index 0000000..f6e14a9 --- /dev/null +++ b/Services/VectorDb/VectorDbManager.cs @@ -0,0 +1,95 @@ +using Foxel.Models.Vector; +using Foxel.Services.Configuration; +using Microsoft.EntityFrameworkCore; + +namespace Foxel.Services.VectorDB; + +public class VectorDbManager(IServiceProvider serviceProvider, IConfigService configService) + : IVectorDbService +{ + private IVectorDbService? _currentService; + private readonly Lock _lock = new(); + private const string VectorDbTypeConfigKey = "VectorDb:Type"; + + private IVectorDbService GetCurrentService() + { + if (_currentService == null) + { + lock (_lock) + { + if (_currentService == null) + { + var dbTypeStr = configService[VectorDbTypeConfigKey] ?? "InMemory"; + if (Enum.TryParse(dbTypeStr, true, out var dbType)) + { + _currentService = CreateVectorDbService(dbType); + } + else + { + _currentService = CreateVectorDbService(VectorDbType.InMemory); + } + } + } + } + + return _currentService; + } + + public async Task SwitchVectorDbAsync(VectorDbType type) + { + IVectorDbService oldService = null; + + lock (_lock) + { + var currentType = GetCurrentVectorDbType(); + if (currentType == type && _currentService != null) + { + return; + } + + oldService = _currentService; + _currentService = CreateVectorDbService(type); + } + + await configService.SetConfigAsync(VectorDbTypeConfigKey, type.ToString(), "向量数据库类型"); + if (type == VectorDbType.InMemory) + { + await BuildUserPictureVectorsAsync(); + } + } + + public VectorDbType GetCurrentVectorDbType() + { + var currentService = GetCurrentService(); + if (currentService is InMemoryVectorDbService) + return VectorDbType.InMemory; + if (currentService is QdrantVectorDbService) + return VectorDbType.Qdrant; + return VectorDbType.InMemory; + } + + private IVectorDbService CreateVectorDbService(VectorDbType type) + { + var dbContextFactory = serviceProvider.GetRequiredService>(); + + return type switch + { + VectorDbType.InMemory => new InMemoryVectorDbService(dbContextFactory), + VectorDbType.Qdrant => new QdrantVectorDbService(dbContextFactory, configService), + _ => new InMemoryVectorDbService(dbContextFactory) + }; + } + + public Task BuildUserPictureVectorsAsync() => GetCurrentService().BuildUserPictureVectorsAsync(); + + public Task> SearchAsync(ReadOnlyMemory query, int? userId, int topK = 10) + => GetCurrentService().SearchAsync(query, userId, topK); + + public Task AddPictureToUserCollectionAsync(int userId, PictureVector pictureVector) + => GetCurrentService().AddPictureToUserCollectionAsync(userId, pictureVector); + + public Task RemovePictureFromUserCollectionAsync(int userId, int pictureId) + => GetCurrentService().RemovePictureFromUserCollectionAsync(userId, pictureId); + + public Task ClearVectorsAsync() => GetCurrentService().ClearVectorsAsync(); +} \ No newline at end of file diff --git a/Web/bun.lock b/Web/bun.lock index e817ea9..50aa5b9 100644 --- a/Web/bun.lock +++ b/Web/bun.lock @@ -4,6 +4,7 @@ "": { "name": "foxel", "dependencies": { + "@ant-design/charts": "^2.3.0", "@ant-design/v5-patch-for-react-19": "^1.0.3", "@types/md5": "^2.3.5", "antd": "^5.24.9", @@ -31,6 +32,10 @@ "packages": { "@ampproject/remapping": ["@ampproject/remapping@2.3.0", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw=="], + "@ant-design/charts": ["@ant-design/charts@2.3.0", "", { "dependencies": { "@ant-design/graphs": "^2.1.0", "@ant-design/plots": "^2.4.0", "lodash": "^4.17.21" }, "peerDependencies": { "react": ">=16.8.4", "react-dom": ">=16.8.4" } }, "sha512-uX/Re6C7t+JleAYKyWu2jv08gAxq2QcZVeGjfgNCV3VC/ODBmqRvu8H0m3Lrla2aHKjCyksirTZI7y2BOKfA1w=="], + + "@ant-design/charts-util": ["@ant-design/charts-util@0.0.1-alpha.7", "", { "dependencies": { "lodash": "^4.17.21" }, "peerDependencies": { "react": ">=16.8.4", "react-dom": ">=16.8.4" } }, "sha512-Yh0o6EdO6SvdSnStFZMbnUzjyymkVzV+TQ9ymVW9hlVgO/fUkUII3JYSdV+UVcFnYwUF0YiDKuSTLCZNAzg2bQ=="], + "@ant-design/colors": ["@ant-design/colors@7.2.0", "", { "dependencies": { "@ant-design/fast-color": "^2.0.6" } }, "sha512-bjTObSnZ9C/O8MB/B4OUtd/q9COomuJAR2SYfhxLyHvCKn4EKwCN3e+fWGMo7H5InAyV0wL17jdE9ALrdOW/6A=="], "@ant-design/cssinjs": ["@ant-design/cssinjs@1.23.0", "", { "dependencies": { "@babel/runtime": "^7.11.1", "@emotion/hash": "^0.8.0", "@emotion/unitless": "^0.7.5", "classnames": "^2.3.1", "csstype": "^3.1.3", "rc-util": "^5.35.0", "stylis": "^4.3.4" }, "peerDependencies": { "react": ">=16.0.0", "react-dom": ">=16.0.0" } }, "sha512-7GAg9bD/iC9ikWatU9ym+P9ugJhi/WbsTWzcKN6T4gU0aehsprtke1UAaaSxxkjjmkJb3llet/rbUSLPgwlY4w=="], @@ -39,14 +44,84 @@ "@ant-design/fast-color": ["@ant-design/fast-color@2.0.6", "", { "dependencies": { "@babel/runtime": "^7.24.7" } }, "sha512-y2217gk4NqL35giHl72o6Zzqji9O7vHh9YmhUVkPtAOpoTCH4uWxo/pr4VE8t0+ChEPs0qo4eJRC5Q1eXWo3vA=="], + "@ant-design/graphs": ["@ant-design/graphs@2.1.0", "", { "dependencies": { "@ant-design/charts-util": "0.0.1-alpha.7", "@antv/g6": "^5.0.44", "@antv/g6-extension-react": "^0.2.0", "@antv/graphin": "^3.0.4", "lodash": "^4.17.21", "styled-components": "^6.1.15" }, "peerDependencies": { "react": ">=16.8.4", "react-dom": ">=16.8.4" } }, "sha512-JavZyJVDRyO5wjReqz3CRYhml5MMpOe+fT4ucebdkfOfWYTlOG+W9vxtNSITJmCGHUVphQkQo9r1CPkZysDT0g=="], + "@ant-design/icons": ["@ant-design/icons@5.6.1", "", { "dependencies": { "@ant-design/colors": "^7.0.0", "@ant-design/icons-svg": "^4.4.0", "@babel/runtime": "^7.24.8", "classnames": "^2.2.6", "rc-util": "^5.31.1" }, "peerDependencies": { "react": ">=16.0.0", "react-dom": ">=16.0.0" } }, "sha512-0/xS39c91WjPAZOWsvi1//zjx6kAp4kxWwctR6kuU6p133w8RU0D2dSCvZC19uQyharg/sAvYxGYWl01BbZZfg=="], "@ant-design/icons-svg": ["@ant-design/icons-svg@4.4.2", "", {}, "sha512-vHbT+zJEVzllwP+CM+ul7reTEfBR0vgxFe7+lREAsAA7YGsYpboiq2sQNeQeRvh09GfQgs/GyFEvZpJ9cLXpXA=="], + "@ant-design/plots": ["@ant-design/plots@2.4.0", "", { "dependencies": { "@ant-design/charts-util": "0.0.1", "@antv/event-emitter": "^0.1.3", "@antv/g": "^6.1.7", "@antv/g2": "^5.2.7", "@antv/g2-extension-plot": "^0.2.1", "lodash": "^4.17.21" }, "peerDependencies": { "react": ">=16.8.4", "react-dom": ">=16.8.4" } }, "sha512-5JxX6gDp9VyQizkQsCBKjGqlHpgKhfV6XTRNqKnrJMYet0FBNO0srDsa/rmQoZZLxMRvE8eZhCXnM7DhRUWUdA=="], + "@ant-design/react-slick": ["@ant-design/react-slick@1.1.2", "", { "dependencies": { "@babel/runtime": "^7.10.4", "classnames": "^2.2.5", "json2mq": "^0.2.0", "resize-observer-polyfill": "^1.5.1", "throttle-debounce": "^5.0.0" }, "peerDependencies": { "react": ">=16.9.0" } }, "sha512-EzlvzE6xQUBrZuuhSAFTdsr4P2bBBHGZwKFemEfq8gIGyIQCxalYfZW/T2ORbtQx5rU69o+WycP3exY/7T1hGA=="], "@ant-design/v5-patch-for-react-19": ["@ant-design/v5-patch-for-react-19@1.0.3", "", { "peerDependencies": { "antd": ">=5.22.6", "react": ">=19.0.0", "react-dom": ">=19.0.0" } }, "sha512-iWfZuSUl5kuhqLUw7jJXUQFMMkM7XpW7apmKzQBQHU0cpifYW4A79xIBt9YVO5IBajKpPG5UKP87Ft7Yrw1p/w=="], + "@antv/algorithm": ["@antv/algorithm@0.1.26", "", { "dependencies": { "@antv/util": "^2.0.13", "tslib": "^2.0.0" } }, "sha512-DVhcFSQ8YQnMNW34Mk8BSsfc61iC1sAnmcfYoXTAshYHuU50p/6b7x3QYaGctDNKWGvi1ub7mPcSY0bK+aN0qg=="], + + "@antv/component": ["@antv/component@2.1.3", "", { "dependencies": { "@antv/g": "^6.1.11", "@antv/scale": "^0.4.16", "@antv/util": "^3.3.10", "svg-path-parser": "^1.1.0" } }, "sha512-TDePMyrx6rvOeUizcKwrNfSb4vL/hcIsIY01dTD1nXKpR3eDf/q558wN4zGH2NmgX/4TOes7UgSH4iCrpB0eMg=="], + + "@antv/coord": ["@antv/coord@0.4.7", "", { "dependencies": { "@antv/scale": "^0.4.12", "@antv/util": "^2.0.13", "gl-matrix": "^3.4.3" } }, "sha512-UTbrMLhwJUkKzqJx5KFnSRpU3BqrdLORJbwUbHK2zHSCT3q3bjcFA//ZYLVfIlwqFDXp/hzfMyRtp0c77A9ZVA=="], + + "@antv/event-emitter": ["@antv/event-emitter@0.1.3", "", {}, "sha512-4ddpsiHN9Pd4UIlWuKVK1C4IiZIdbwQvy9i7DUSI3xNJ89FPUFt8lxDYj8GzzfdllV0NkJTRxnG+FvLk0llidg=="], + + "@antv/expr": ["@antv/expr@1.0.2", "", {}, "sha512-vrfdmPHkTuiS5voVutKl2l06w1ihBh9A8SFdQPEE+2KMVpkymzGOF1eWpfkbGZ7tiFE15GodVdhhHomD/hdIwg=="], + + "@antv/g": ["@antv/g@6.1.25", "", { "dependencies": { "@antv/g-camera-api": "2.0.38", "@antv/g-dom-mutation-observer-api": "2.0.35", "@antv/g-lite": "2.2.19", "@antv/g-web-animations-api": "2.1.25", "@babel/runtime": "^7.25.6" } }, "sha512-qkXztWRVYQDl/x3tlA9Oww5DwaBCDDYXq6Wai9jfO8TZeIV3T8Dbw5eG/M115doyHX2vIVRkrE6+xiFe5weIHQ=="], + + "@antv/g-camera-api": ["@antv/g-camera-api@2.0.38", "", { "dependencies": { "@antv/g-lite": "2.2.19", "@antv/util": "^3.3.5", "@babel/runtime": "^7.25.6", "gl-matrix": "^3.4.3", "tslib": "^2.5.3" } }, "sha512-BgFkUMcTO06Oz37Z+hVqxATwdWFE5DfBgMKlFaMwKKF/8n+7eNhlif1KBfcf2rEfGijS0FD0ZGKCr9uJ06+GIg=="], + + "@antv/g-canvas": ["@antv/g-canvas@2.0.43", "", { "dependencies": { "@antv/g-lite": "2.2.19", "@antv/g-plugin-canvas-path-generator": "2.1.19", "@antv/g-plugin-canvas-picker": "2.1.22", "@antv/g-plugin-canvas-renderer": "2.2.22", "@antv/g-plugin-dom-interaction": "2.1.24", "@antv/g-plugin-html-renderer": "2.1.24", "@antv/g-plugin-image-loader": "2.1.22", "@antv/util": "^3.3.5", "@babel/runtime": "^7.25.6", "tslib": "^2.5.3" } }, "sha512-iAMX+b1eEhwddhm7qiQAtNsnwJQDQsiE5/ELgzni0UHF28zMVTlc5FdDMXKLPuaYs9S/dw/MXBtqctRj2IjA1g=="], + + "@antv/g-dom-mutation-observer-api": ["@antv/g-dom-mutation-observer-api@2.0.35", "", { "dependencies": { "@antv/g-lite": "2.2.19", "@babel/runtime": "^7.25.6" } }, "sha512-bAl3ViXDHvLEbGvGZwZBg4gpoNjUTwVQ3XTmRAkymkFGkUy+KV0ZwFdqEegP25TQGPl85er/hB6MCu6Yt58AJA=="], + + "@antv/g-lite": ["@antv/g-lite@2.2.19", "", { "dependencies": { "@antv/g-math": "3.0.1", "@antv/util": "^3.3.5", "@antv/vendor": "^1.0.3", "@babel/runtime": "^7.25.6", "eventemitter3": "^5.0.1", "gl-matrix": "^3.4.3", "rbush": "^3.0.1", "tslib": "^2.5.3" } }, "sha512-QfxZsbLGTSGL18NgSOAVQURXC3xMXbmmS125EF7/vCzW2Lw2nF5I8k0KW4N09ty+/FtVpSESJX652g2phIvd5g=="], + + "@antv/g-math": ["@antv/g-math@3.0.1", "", { "dependencies": { "@antv/util": "^3.3.5", "@babel/runtime": "^7.25.6", "gl-matrix": "^3.4.3", "tslib": "^2.5.3" } }, "sha512-FvkDBNRpj+HsLINunrL2PW0OlG368MlpHuihbxleuajGim5kra8tgISwCLmAf8Yz2b1CgZ9PvpohqiLzHS7HLg=="], + + "@antv/g-plugin-canvas-path-generator": ["@antv/g-plugin-canvas-path-generator@2.1.19", "", { "dependencies": { "@antv/g-lite": "2.2.19", "@antv/g-math": "3.0.1", "@antv/util": "^3.3.5", "@babel/runtime": "^7.25.6", "tslib": "^2.5.3" } }, "sha512-+tc97NLvVYEFQnrLffmyxPpVXwUuTPbXBGy3aUTBYKd3YXhFBIKJYpQR39jsX2skgUvLh/67ZtA9QeUt6U41oQ=="], + + "@antv/g-plugin-canvas-picker": ["@antv/g-plugin-canvas-picker@2.1.22", "", { "dependencies": { "@antv/g-lite": "2.2.19", "@antv/g-math": "3.0.1", "@antv/g-plugin-canvas-path-generator": "2.1.19", "@antv/g-plugin-canvas-renderer": "2.2.22", "@antv/util": "^3.3.5", "@babel/runtime": "^7.25.6", "gl-matrix": "^3.4.3", "tslib": "^2.5.3" } }, "sha512-Pm/N+YTFOlXtjPran3wfN7Iuv0i2YglXrByxvBY8IQ3IzmB68+yZr+yPNRqjgbIM0yh45vIxz3SB/7VwYDPXMA=="], + + "@antv/g-plugin-canvas-renderer": ["@antv/g-plugin-canvas-renderer@2.2.22", "", { "dependencies": { "@antv/g-lite": "2.2.19", "@antv/g-math": "3.0.1", "@antv/g-plugin-canvas-path-generator": "2.1.19", "@antv/g-plugin-image-loader": "2.1.22", "@antv/util": "^3.3.5", "@babel/runtime": "^7.25.6", "gl-matrix": "^3.4.3", "tslib": "^2.5.3" } }, "sha512-+KyorG9lmwx5mogYZ6DP6BaiE9bnGUHojUxg+pTq032dx3SkCkLBl+CB5pZz1C2LEiQ+NkYtP3PlEjgSeeR/9A=="], + + "@antv/g-plugin-dom-interaction": ["@antv/g-plugin-dom-interaction@2.1.24", "", { "dependencies": { "@antv/g-lite": "2.2.19", "@babel/runtime": "^7.25.6", "tslib": "^2.5.3" } }, "sha512-1IrsUp2k+4oi2brVNstgxoisdwcdwqSNdEYJBDtVP1Bv5KZabKSs9lxlkxVR0DTb8BJtWBi80gmKQFIJ8znofQ=="], + + "@antv/g-plugin-dragndrop": ["@antv/g-plugin-dragndrop@2.0.35", "", { "dependencies": { "@antv/g-lite": "2.2.19", "@antv/util": "^3.3.5", "@babel/runtime": "^7.25.6", "tslib": "^2.5.3" } }, "sha512-1ZG+j91uEQAiFN0UqRkYCx3G8WWlKYoCXgTTx6m4YFJESJiab5M1C4OAi7zXclt1maOR154x3L/j3sRmBHFA+A=="], + + "@antv/g-plugin-html-renderer": ["@antv/g-plugin-html-renderer@2.1.24", "", { "dependencies": { "@antv/g-lite": "2.2.19", "@antv/util": "^3.3.5", "@babel/runtime": "^7.25.6", "gl-matrix": "^3.4.3", "tslib": "^2.5.3" } }, "sha512-UPEitSu5F42kRgqy8Cr34aC6O4+0cCnC+avv0ZMXUFOf7AMhMnjQLlHHo+GDfM/0r6m//0ZCsqHpv8vB0A+sUA=="], + + "@antv/g-plugin-image-loader": ["@antv/g-plugin-image-loader@2.1.22", "", { "dependencies": { "@antv/g-lite": "2.2.19", "@antv/util": "^3.3.5", "@babel/runtime": "^7.25.6", "gl-matrix": "^3.4.3", "tslib": "^2.5.3" } }, "sha512-moA+EnV8Gnofj5Kk6btQ6DrufPYiGMvGWXrkBqHNrowfIUD+bFfHPnLm4gV52hHKYEvwnIP2XL+ayHRvzVyffw=="], + + "@antv/g-plugin-svg-picker": ["@antv/g-plugin-svg-picker@2.0.38", "", { "dependencies": { "@antv/g-lite": "2.2.19", "@antv/g-plugin-svg-renderer": "2.2.20", "@babel/runtime": "^7.25.6", "tslib": "^2.5.3" } }, "sha512-9XuT3VRFtUrdhMYmib7uB/sjXG9orQ7yGzIwYp+mCI734mnmJApOrB+J3UcSt3s+1PAIcABQkHT1MRxFII2w7w=="], + + "@antv/g-plugin-svg-renderer": ["@antv/g-plugin-svg-renderer@2.2.20", "", { "dependencies": { "@antv/g-lite": "2.2.19", "@antv/util": "^3.3.5", "@babel/runtime": "^7.25.6", "gl-matrix": "^3.4.3", "tslib": "^2.5.3" } }, "sha512-HjLyQMcMm/kRVhwkmdEkWGGZAHUhIuyztOzO0dzWucfGqXsusNZvKHpiWUMl3DBm6ID6qziYCRw5IIpqlsh3Jw=="], + + "@antv/g-svg": ["@antv/g-svg@2.0.38", "", { "dependencies": { "@antv/g-lite": "2.2.19", "@antv/g-plugin-dom-interaction": "2.1.24", "@antv/g-plugin-svg-picker": "2.0.38", "@antv/g-plugin-svg-renderer": "2.2.20", "@antv/util": "^3.3.5", "@babel/runtime": "^7.25.6", "tslib": "^2.5.3" } }, "sha512-S11RB+4Yh3nel+wHChcbB4TlaJFyKl4gP9sUUgUzwgWiAFNxiHU4fM3+sb3f4AQyToIZZd1sqH0TscQ3psX5Yg=="], + + "@antv/g-web-animations-api": ["@antv/g-web-animations-api@2.1.25", "", { "dependencies": { "@antv/g-lite": "2.2.19", "@antv/util": "^3.3.5", "@babel/runtime": "^7.25.6", "tslib": "^2.5.3" } }, "sha512-xljNU+mDsdaDr+DwP77te2ZkNLcLiwuwppwXuRRpv/wVxUue726c/QbfYj/wMwJoBcOEtl/5hjAks/+gdvr3ag=="], + + "@antv/g2": ["@antv/g2@5.3.3", "", { "dependencies": { "@antv/component": "^2.1.2", "@antv/coord": "^0.4.7", "@antv/event-emitter": "^0.1.3", "@antv/expr": "^1.0.2", "@antv/g": "^6.1.23", "@antv/g-canvas": "^2.0.42", "@antv/g-plugin-dragndrop": "^2.0.34", "@antv/scale": "^0.4.16", "@antv/util": "^3.3.10", "@antv/vendor": "^1.0.8", "flru": "^1.0.2", "pdfast": "^0.2.0" } }, "sha512-K+Pf1ZRslGn2IHQzA+2NrukeaNqrpOZB76zytkmt5bhGOhZgSWSfc9ubxi0OAlrBY+Yc6DfYcLiHziuASYoG5w=="], + + "@antv/g2-extension-plot": ["@antv/g2-extension-plot@0.2.2", "", { "dependencies": { "@antv/g2": "^5.1.8", "@antv/util": "^3.3.5", "@antv/vendor": "^1.0.10" } }, "sha512-KJXCXO7as+h0hDqirGXf1omrNuYzQmY3VmBmp7lIvkepbQ7sz3pPwy895r1FWETGF3vTk5UeFcAF5yzzBHWgbw=="], + + "@antv/g6": ["@antv/g6@5.0.48", "", { "dependencies": { "@antv/algorithm": "^0.1.26", "@antv/component": "^2.1.3", "@antv/event-emitter": "^0.1.3", "@antv/g": "^6.1.24", "@antv/g-canvas": "^2.0.43", "@antv/g-plugin-dragndrop": "^2.0.35", "@antv/graphlib": "^2.0.4", "@antv/hierarchy": "^0.6.14", "@antv/layout": "1.2.14-beta.9", "@antv/util": "^3.3.10", "bubblesets-js": "^2.3.4" } }, "sha512-ngACp0NTJE1Dg03myB6Tqj0iVALiwEl83sul+xFqwASxjmw9dv3UeGa6tFGDp+4QvzXSh5GM8SlbTMTlfgEMnQ=="], + + "@antv/g6-extension-react": ["@antv/g6-extension-react@0.2.3", "", { "dependencies": { "@antv/g": "^6.1.24", "@antv/g-svg": "^2.0.38" }, "peerDependencies": { "@antv/g6": "^5.0.47", "react": ">=16.8", "react-dom": ">=16.8" } }, "sha512-CUEeMSqC6B1oZN3Sfq8hN3rWRCt4JhEF32Sqa/RXv7sRnJzLU9o98XqN2DjFgsQ8CpKN/MkRiR73/9zkJBGOMg=="], + + "@antv/graphin": ["@antv/graphin@3.0.5", "", { "dependencies": { "@antv/g6": "^5.0.28" }, "peerDependencies": { "react": "^18.0.0 || ^19.1.0", "react-dom": "^18.0.0 || ^19.1.0" } }, "sha512-V/j8R8Ty44wUqxVIYLdpPuIO8WWCTIVq1eBJg5YRunL5t5o5qAFpC/qkQxslbBMWyKdIH0oWBnvHA74riGi7cw=="], + + "@antv/graphlib": ["@antv/graphlib@2.0.4", "", { "dependencies": { "@antv/event-emitter": "^0.1.3" } }, "sha512-zc/5oQlsdk42Z0ib1mGklwzhJ5vczLFiPa1v7DgJkTbgJ2YxRh9xdarf86zI49sKVJmgbweRpJs7Nu5bIiwv4w=="], + + "@antv/hierarchy": ["@antv/hierarchy@0.6.14", "", {}, "sha512-V3uknf7bhynOqQDw2sg+9r9DwZ9pc6k/EcqyTFdfXB1+ydr7urisP0MipIuimucvQKN+Qkd+d6w601r1UIroqQ=="], + + "@antv/layout": ["@antv/layout@1.2.14-beta.9", "", { "dependencies": { "@antv/event-emitter": "^0.1.3", "@antv/graphlib": "^2.0.0", "@antv/util": "^3.3.2", "@naoak/workerize-transferable": "^0.1.0", "comlink": "^4.4.1", "d3-force": "^3.0.0", "d3-force-3d": "^3.0.5", "d3-octree": "^1.0.2", "d3-quadtree": "^3.0.1", "dagre": "^0.8.5", "ml-matrix": "^6.10.4", "tslib": "^2.5.0" } }, "sha512-wPlwBFMtq2lWZFc89/7Lzb8fjHnyKVZZ9zBb2h+zZIP0YWmVmHRE8+dqCiPKOyOGUXEdDtn813f1g107dCHZlg=="], + + "@antv/scale": ["@antv/scale@0.4.16", "", { "dependencies": { "@antv/util": "^3.3.7", "color-string": "^1.5.5", "fecha": "^4.2.1" } }, "sha512-5wg/zB5kXHxpTV5OYwJD3ja6R8yTiqIOkjOhmpEJiowkzRlbEC/BOyMvNUq5fqFIHnMCE9woO7+c3zxEQCKPjw=="], + + "@antv/util": ["@antv/util@3.3.10", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "gl-matrix": "^3.3.0", "tslib": "^2.3.1" } }, "sha512-basGML3DFA3O87INnzvDStjzS+n0JLEhRnRsDzP9keiXz8gT1z/fTdmJAZFOzMMWxy+HKbi7NbSt0+8vz/OsBQ=="], + + "@antv/vendor": ["@antv/vendor@1.0.11", "", { "dependencies": { "@types/d3-array": "^3.2.1", "@types/d3-color": "^3.1.3", "@types/d3-dispatch": "^3.0.6", "@types/d3-dsv": "^3.0.7", "@types/d3-ease": "^3.0.2", "@types/d3-fetch": "^3.0.7", "@types/d3-force": "^3.0.10", "@types/d3-format": "^3.0.4", "@types/d3-geo": "^3.1.0", "@types/d3-hierarchy": "^3.1.7", "@types/d3-interpolate": "^3.0.4", "@types/d3-path": "^3.1.0", "@types/d3-quadtree": "^3.0.6", "@types/d3-random": "^3.0.3", "@types/d3-scale": "^4.0.9", "@types/d3-scale-chromatic": "^3.1.0", "@types/d3-shape": "^3.1.7", "@types/d3-time": "^3.0.4", "@types/d3-timer": "^3.0.2", "d3-array": "^3.2.4", "d3-color": "^3.1.0", "d3-dispatch": "^3.0.1", "d3-dsv": "^3.0.1", "d3-ease": "^3.0.1", "d3-fetch": "^3.0.1", "d3-force": "^3.0.0", "d3-force-3d": "^3.0.5", "d3-format": "^3.1.0", "d3-geo": "^3.1.1", "d3-geo-projection": "^4.0.0", "d3-hierarchy": "^3.1.2", "d3-interpolate": "^3.0.1", "d3-path": "^3.1.0", "d3-quadtree": "^3.0.1", "d3-random": "^3.0.1", "d3-regression": "^1.3.10", "d3-scale": "^4.0.2", "d3-scale-chromatic": "^3.1.0", "d3-shape": "^3.2.0", "d3-time": "^3.1.0", "d3-timer": "^3.0.1" } }, "sha512-LmhPEQ+aapk3barntaiIxJ5VHno/Tyab2JnfdcPzp5xONh/8VSfed4bo/9xKo5HcUAEydko38vYLfj6lJliLiw=="], + "@babel/code-frame": ["@babel/code-frame@7.27.1", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg=="], "@babel/compat-data": ["@babel/compat-data@7.27.2", "", {}, "sha512-TUtMJYRPyUb/9aU8f3K0mjmjf6M9N5Woshn2CS6nqJSeJtTtQcpLUXjGt9vbF8ZGff0El99sWkLgzwW3VXnxZQ=="], @@ -87,6 +162,10 @@ "@emotion/hash": ["@emotion/hash@0.8.0", "", {}, "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow=="], + "@emotion/is-prop-valid": ["@emotion/is-prop-valid@1.2.2", "", { "dependencies": { "@emotion/memoize": "^0.8.1" } }, "sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw=="], + + "@emotion/memoize": ["@emotion/memoize@0.8.1", "", {}, "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA=="], + "@emotion/unitless": ["@emotion/unitless@0.7.5", "", {}, "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg=="], "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.4", "", { "os": "aix", "cpu": "ppc64" }, "sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q=="], @@ -171,10 +250,14 @@ "@jridgewell/set-array": ["@jridgewell/set-array@1.2.1", "", {}, "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A=="], + "@jridgewell/source-map": ["@jridgewell/source-map@0.3.6", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25" } }, "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ=="], + "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.0", "", {}, "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ=="], "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.25", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ=="], + "@naoak/workerize-transferable": ["@naoak/workerize-transferable@0.1.0", "", { "peerDependencies": { "workerize-loader": "*" } }, "sha512-fDLfuP71IPNP5+zSfxFb52OHgtjZvauRJWbVnpzQ7G7BjcbLjTny0OW1d3ZO806XKpLWNKmeeW3MhE0sy8iwYQ=="], + "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="], "@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="], @@ -247,16 +330,64 @@ "@types/babel__traverse": ["@types/babel__traverse@7.20.7", "", { "dependencies": { "@babel/types": "^7.20.7" } }, "sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng=="], + "@types/d3-array": ["@types/d3-array@3.2.1", "", {}, "sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg=="], + + "@types/d3-color": ["@types/d3-color@3.1.3", "", {}, "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A=="], + + "@types/d3-dispatch": ["@types/d3-dispatch@3.0.6", "", {}, "sha512-4fvZhzMeeuBJYZXRXrRIQnvUYfyXwYmLsdiN7XXmVNQKKw1cM8a5WdID0g1hVFZDqT9ZqZEY5pD44p24VS7iZQ=="], + + "@types/d3-dsv": ["@types/d3-dsv@3.0.7", "", {}, "sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g=="], + + "@types/d3-ease": ["@types/d3-ease@3.0.2", "", {}, "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA=="], + + "@types/d3-fetch": ["@types/d3-fetch@3.0.7", "", { "dependencies": { "@types/d3-dsv": "*" } }, "sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA=="], + + "@types/d3-force": ["@types/d3-force@3.0.10", "", {}, "sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw=="], + + "@types/d3-format": ["@types/d3-format@3.0.4", "", {}, "sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g=="], + + "@types/d3-geo": ["@types/d3-geo@3.1.0", "", { "dependencies": { "@types/geojson": "*" } }, "sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ=="], + + "@types/d3-hierarchy": ["@types/d3-hierarchy@3.1.7", "", {}, "sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg=="], + + "@types/d3-interpolate": ["@types/d3-interpolate@3.0.4", "", { "dependencies": { "@types/d3-color": "*" } }, "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA=="], + + "@types/d3-path": ["@types/d3-path@3.1.1", "", {}, "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg=="], + + "@types/d3-quadtree": ["@types/d3-quadtree@3.0.6", "", {}, "sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg=="], + + "@types/d3-random": ["@types/d3-random@3.0.3", "", {}, "sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ=="], + + "@types/d3-scale": ["@types/d3-scale@4.0.9", "", { "dependencies": { "@types/d3-time": "*" } }, "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw=="], + + "@types/d3-scale-chromatic": ["@types/d3-scale-chromatic@3.1.0", "", {}, "sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ=="], + + "@types/d3-shape": ["@types/d3-shape@3.1.7", "", { "dependencies": { "@types/d3-path": "*" } }, "sha512-VLvUQ33C+3J+8p+Daf+nYSOsjB4GXp19/S/aGo60m9h1v6XaxjiT82lKVWJCfzhtuZ3yD7i/TPeC/fuKLLOSmg=="], + + "@types/d3-time": ["@types/d3-time@3.0.4", "", {}, "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g=="], + + "@types/d3-timer": ["@types/d3-timer@3.0.2", "", {}, "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw=="], + + "@types/eslint": ["@types/eslint@9.6.1", "", { "dependencies": { "@types/estree": "*", "@types/json-schema": "*" } }, "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag=="], + + "@types/eslint-scope": ["@types/eslint-scope@3.7.7", "", { "dependencies": { "@types/eslint": "*", "@types/estree": "*" } }, "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg=="], + "@types/estree": ["@types/estree@1.0.7", "", {}, "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ=="], + "@types/geojson": ["@types/geojson@7946.0.16", "", {}, "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg=="], + "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="], "@types/md5": ["@types/md5@2.3.5", "", {}, "sha512-/i42wjYNgE6wf0j2bcTX6kuowmdL/6PE4IVitMpm2eYKBUuYCprdcWVK+xEF0gcV6ufMCRhtxmReGfc6hIK7Jw=="], + "@types/node": ["@types/node@22.15.21", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-EV/37Td6c+MgKAbkcLG6vqZ2zEYHD7bvSrzqqs2RIhbA6w3x+Dqz8MZM3sP6kGTeLrdoOgKZe+Xja7tUB2DNkQ=="], + "@types/react": ["@types/react@19.1.4", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-EB1yiiYdvySuIITtD5lhW4yPyJ31RkJkkDw794LaQYrxCSaQV/47y5o1FMC4zF9ZyjUjzJMZwbovEnT5yHTW6g=="], "@types/react-dom": ["@types/react-dom@19.1.5", "", { "peerDependencies": { "@types/react": "^19.0.0" } }, "sha512-CMCjrWucUBZvohgZxkjd6S9h0nZxXjzus6yDfUb+xLxYM7VvjKNH1tQrE9GWLql1XoOP4/Ds3bwFqShHUYraGg=="], + "@types/stylis": ["@types/stylis@4.2.5", "", {}, "sha512-1Xve+NMN7FWjY14vLoY5tL3BVEQ/n42YLwaqJIPYhotZ9uBHt87VceMwWQpzmdEt2TNXIorIFG+YeCUUW7RInw=="], + "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.32.1", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.32.1", "@typescript-eslint/type-utils": "8.32.1", "@typescript-eslint/utils": "8.32.1", "@typescript-eslint/visitor-keys": "8.32.1", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-6u6Plg9nP/J1GRpe/vcjjabo6Uc5YQPAMxsgQyGC/I0RuukiG1wIe3+Vtg3IrSCVJDmqK3j8adrtzXSENRtFgg=="], "@typescript-eslint/parser": ["@typescript-eslint/parser@8.32.1", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.32.1", "@typescript-eslint/types": "8.32.1", "@typescript-eslint/typescript-estree": "8.32.1", "@typescript-eslint/visitor-keys": "8.32.1", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-LKMrmwCPoLhM45Z00O1ulb6jwyVr2kr3XJp+G+tSEZcbauNnScewcQwtJqXDhXeYPDEjZ8C1SjXm015CirEmGg=="], @@ -275,12 +406,50 @@ "@vitejs/plugin-react": ["@vitejs/plugin-react@4.4.1", "", { "dependencies": { "@babel/core": "^7.26.10", "@babel/plugin-transform-react-jsx-self": "^7.25.9", "@babel/plugin-transform-react-jsx-source": "^7.25.9", "@types/babel__core": "^7.20.5", "react-refresh": "^0.17.0" }, "peerDependencies": { "vite": "^4.2.0 || ^5.0.0 || ^6.0.0" } }, "sha512-IpEm5ZmeXAP/osiBXVVP5KjFMzbWOonMs0NaQQl+xYnUAcq4oHUBsF2+p4MgKWG4YMmFYJU8A6sxRPuowllm6w=="], + "@webassemblyjs/ast": ["@webassemblyjs/ast@1.14.1", "", { "dependencies": { "@webassemblyjs/helper-numbers": "1.13.2", "@webassemblyjs/helper-wasm-bytecode": "1.13.2" } }, "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ=="], + + "@webassemblyjs/floating-point-hex-parser": ["@webassemblyjs/floating-point-hex-parser@1.13.2", "", {}, "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA=="], + + "@webassemblyjs/helper-api-error": ["@webassemblyjs/helper-api-error@1.13.2", "", {}, "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ=="], + + "@webassemblyjs/helper-buffer": ["@webassemblyjs/helper-buffer@1.14.1", "", {}, "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA=="], + + "@webassemblyjs/helper-numbers": ["@webassemblyjs/helper-numbers@1.13.2", "", { "dependencies": { "@webassemblyjs/floating-point-hex-parser": "1.13.2", "@webassemblyjs/helper-api-error": "1.13.2", "@xtuc/long": "4.2.2" } }, "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA=="], + + "@webassemblyjs/helper-wasm-bytecode": ["@webassemblyjs/helper-wasm-bytecode@1.13.2", "", {}, "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA=="], + + "@webassemblyjs/helper-wasm-section": ["@webassemblyjs/helper-wasm-section@1.14.1", "", { "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", "@webassemblyjs/helper-wasm-bytecode": "1.13.2", "@webassemblyjs/wasm-gen": "1.14.1" } }, "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw=="], + + "@webassemblyjs/ieee754": ["@webassemblyjs/ieee754@1.13.2", "", { "dependencies": { "@xtuc/ieee754": "^1.2.0" } }, "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw=="], + + "@webassemblyjs/leb128": ["@webassemblyjs/leb128@1.13.2", "", { "dependencies": { "@xtuc/long": "4.2.2" } }, "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw=="], + + "@webassemblyjs/utf8": ["@webassemblyjs/utf8@1.13.2", "", {}, "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ=="], + + "@webassemblyjs/wasm-edit": ["@webassemblyjs/wasm-edit@1.14.1", "", { "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", "@webassemblyjs/helper-wasm-bytecode": "1.13.2", "@webassemblyjs/helper-wasm-section": "1.14.1", "@webassemblyjs/wasm-gen": "1.14.1", "@webassemblyjs/wasm-opt": "1.14.1", "@webassemblyjs/wasm-parser": "1.14.1", "@webassemblyjs/wast-printer": "1.14.1" } }, "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ=="], + + "@webassemblyjs/wasm-gen": ["@webassemblyjs/wasm-gen@1.14.1", "", { "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-wasm-bytecode": "1.13.2", "@webassemblyjs/ieee754": "1.13.2", "@webassemblyjs/leb128": "1.13.2", "@webassemblyjs/utf8": "1.13.2" } }, "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg=="], + + "@webassemblyjs/wasm-opt": ["@webassemblyjs/wasm-opt@1.14.1", "", { "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", "@webassemblyjs/wasm-gen": "1.14.1", "@webassemblyjs/wasm-parser": "1.14.1" } }, "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw=="], + + "@webassemblyjs/wasm-parser": ["@webassemblyjs/wasm-parser@1.14.1", "", { "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-api-error": "1.13.2", "@webassemblyjs/helper-wasm-bytecode": "1.13.2", "@webassemblyjs/ieee754": "1.13.2", "@webassemblyjs/leb128": "1.13.2", "@webassemblyjs/utf8": "1.13.2" } }, "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ=="], + + "@webassemblyjs/wast-printer": ["@webassemblyjs/wast-printer@1.14.1", "", { "dependencies": { "@webassemblyjs/ast": "1.14.1", "@xtuc/long": "4.2.2" } }, "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw=="], + + "@xtuc/ieee754": ["@xtuc/ieee754@1.2.0", "", {}, "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA=="], + + "@xtuc/long": ["@xtuc/long@4.2.2", "", {}, "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ=="], + "acorn": ["acorn@8.14.1", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg=="], "acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="], "ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="], + "ajv-formats": ["ajv-formats@2.1.1", "", { "dependencies": { "ajv": "^8.0.0" } }, "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA=="], + + "ajv-keywords": ["ajv-keywords@5.1.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3" }, "peerDependencies": { "ajv": "^8.8.2" } }, "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw=="], + "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], "antd": ["antd@5.25.1", "", { "dependencies": { "@ant-design/colors": "^7.2.0", "@ant-design/cssinjs": "^1.23.0", "@ant-design/cssinjs-utils": "^1.1.3", "@ant-design/fast-color": "^2.0.6", "@ant-design/icons": "^5.6.1", "@ant-design/react-slick": "~1.1.2", "@babel/runtime": "^7.26.0", "@rc-component/color-picker": "~2.0.1", "@rc-component/mutate-observer": "^1.1.0", "@rc-component/qrcode": "~1.0.0", "@rc-component/tour": "~1.15.1", "@rc-component/trigger": "^2.2.6", "classnames": "^2.5.1", "copy-to-clipboard": "^3.3.3", "dayjs": "^1.11.11", "rc-cascader": "~3.34.0", "rc-checkbox": "~3.5.0", "rc-collapse": "~3.9.0", "rc-dialog": "~9.6.0", "rc-drawer": "~7.2.0", "rc-dropdown": "~4.2.1", "rc-field-form": "~2.7.0", "rc-image": "~7.12.0", "rc-input": "~1.8.0", "rc-input-number": "~9.5.0", "rc-mentions": "~2.20.0", "rc-menu": "~9.16.1", "rc-motion": "^2.9.5", "rc-notification": "~5.6.4", "rc-pagination": "~5.1.0", "rc-picker": "~4.11.3", "rc-progress": "~4.0.0", "rc-rate": "~2.13.1", "rc-resize-observer": "^1.4.3", "rc-segmented": "~2.7.0", "rc-select": "~14.16.7", "rc-slider": "~11.1.8", "rc-steps": "~6.0.1", "rc-switch": "~4.1.0", "rc-table": "~7.50.4", "rc-tabs": "~15.6.1", "rc-textarea": "~1.10.0", "rc-tooltip": "~6.4.0", "rc-tree": "~5.13.1", "rc-tree-select": "~5.27.0", "rc-upload": "~4.9.0", "rc-util": "^5.44.4", "scroll-into-view-if-needed": "^3.1.0", "throttle-debounce": "^5.0.2" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-4KC7KuPCjr0z3Vuw9DsF+ceqJaPLbuUI3lOX1sY8ix25ceamp+P8yxOmk3Y2JHCD2ZAhq+5IQ/DTJRN2adWYKQ=="], @@ -289,26 +458,42 @@ "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + "big.js": ["big.js@5.2.2", "", {}, "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ=="], + "brace-expansion": ["brace-expansion@1.1.11", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA=="], "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], "browserslist": ["browserslist@4.24.5", "", { "dependencies": { "caniuse-lite": "^1.0.30001716", "electron-to-chromium": "^1.5.149", "node-releases": "^2.0.19", "update-browserslist-db": "^1.1.3" }, "bin": { "browserslist": "cli.js" } }, "sha512-FDToo4Wo82hIdgc1CQ+NQD0hEhmpPjrZ3hiUgwgOG6IuTdlpr8jdjyG24P6cNP1yJpTLzS5OcGgSw0xmDU1/Tw=="], + "bubblesets-js": ["bubblesets-js@2.3.4", "", {}, "sha512-DyMjHmpkS2+xcFNtyN00apJYL3ESdp9fTrkDr5+9Qg/GPqFmcWgGsK1akZnttE1XFxJ/VMy4DNNGMGYtmFp1Sg=="], + + "buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="], + "callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="], + "camelize": ["camelize@1.0.1", "", {}, "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ=="], + "caniuse-lite": ["caniuse-lite@1.0.30001718", "", {}, "sha512-AflseV1ahcSunK53NfEs9gFWgOEmzr0f+kaMFA4xiLZlr9Hzt7HxcSpIFcnNCUkz6R6dWKa54rUz3HUmI3nVcw=="], "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], "charenc": ["charenc@0.0.2", "", {}, "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA=="], + "chrome-trace-event": ["chrome-trace-event@1.0.4", "", {}, "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ=="], + "classnames": ["classnames@2.5.1", "", {}, "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow=="], "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], + "color-string": ["color-string@1.9.1", "", { "dependencies": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" } }, "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg=="], + + "comlink": ["comlink@4.4.2", "", {}, "sha512-OxGdvBmJuNKSCMO4NTl1L47VRp6xn2wG4F/2hYzB6tiCb709otOxtEYCSvK80PtjODfXXZu8ds+Nw5kVCjqd2g=="], + + "commander": ["commander@7.2.0", "", {}, "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw=="], + "compute-scroll-into-view": ["compute-scroll-into-view@3.1.1", "", {}, "sha512-VRhuHOLoKYOy4UbilLbUzbYg93XLjv2PncJC50EuTWPA3gaja1UjBsUP/D/9/juV3vQFr6XBEzn9KCAHdUvOHw=="], "concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="], @@ -323,8 +508,64 @@ "crypt": ["crypt@0.0.2", "", {}, "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow=="], + "css-color-keywords": ["css-color-keywords@1.0.0", "", {}, "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg=="], + + "css-to-react-native": ["css-to-react-native@3.2.0", "", { "dependencies": { "camelize": "^1.0.0", "css-color-keywords": "^1.0.0", "postcss-value-parser": "^4.0.2" } }, "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ=="], + "csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="], + "d3-array": ["d3-array@3.2.4", "", { "dependencies": { "internmap": "1 - 2" } }, "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg=="], + + "d3-binarytree": ["d3-binarytree@1.0.2", "", {}, "sha512-cElUNH+sHu95L04m92pG73t2MEJXKu+GeKUN1TJkFsu93E5W8E9Sc3kHEGJKgenGvj19m6upSn2EunvMgMD2Yw=="], + + "d3-color": ["d3-color@3.1.0", "", {}, "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA=="], + + "d3-dispatch": ["d3-dispatch@3.0.1", "", {}, "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg=="], + + "d3-dsv": ["d3-dsv@3.0.1", "", { "dependencies": { "commander": "7", "iconv-lite": "0.6", "rw": "1" }, "bin": { "csv2json": "bin/dsv2json.js", "csv2tsv": "bin/dsv2dsv.js", "dsv2dsv": "bin/dsv2dsv.js", "dsv2json": "bin/dsv2json.js", "json2csv": "bin/json2dsv.js", "json2dsv": "bin/json2dsv.js", "json2tsv": "bin/json2dsv.js", "tsv2csv": "bin/dsv2dsv.js", "tsv2json": "bin/dsv2json.js" } }, "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q=="], + + "d3-ease": ["d3-ease@3.0.1", "", {}, "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w=="], + + "d3-fetch": ["d3-fetch@3.0.1", "", { "dependencies": { "d3-dsv": "1 - 3" } }, "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw=="], + + "d3-force": ["d3-force@3.0.0", "", { "dependencies": { "d3-dispatch": "1 - 3", "d3-quadtree": "1 - 3", "d3-timer": "1 - 3" } }, "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg=="], + + "d3-force-3d": ["d3-force-3d@3.0.6", "", { "dependencies": { "d3-binarytree": "1", "d3-dispatch": "1 - 3", "d3-octree": "1", "d3-quadtree": "1 - 3", "d3-timer": "1 - 3" } }, "sha512-4tsKHUPLOVkyfEffZo1v6sFHvGFwAIIjt/W8IThbp08DYAsXZck+2pSHEG5W1+gQgEvFLdZkYvmJAbRM2EzMnA=="], + + "d3-format": ["d3-format@3.1.0", "", {}, "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA=="], + + "d3-geo": ["d3-geo@3.1.1", "", { "dependencies": { "d3-array": "2.5.0 - 3" } }, "sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q=="], + + "d3-geo-projection": ["d3-geo-projection@4.0.0", "", { "dependencies": { "commander": "7", "d3-array": "1 - 3", "d3-geo": "1.12.0 - 3" }, "bin": { "geo2svg": "bin/geo2svg.js", "geograticule": "bin/geograticule.js", "geoproject": "bin/geoproject.js", "geoquantize": "bin/geoquantize.js", "geostitch": "bin/geostitch.js" } }, "sha512-p0bK60CEzph1iqmnxut7d/1kyTmm3UWtPlwdkM31AU+LW+BXazd5zJdoCn7VFxNCHXRngPHRnsNn5uGjLRGndg=="], + + "d3-hierarchy": ["d3-hierarchy@3.1.2", "", {}, "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA=="], + + "d3-interpolate": ["d3-interpolate@3.0.1", "", { "dependencies": { "d3-color": "1 - 3" } }, "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g=="], + + "d3-octree": ["d3-octree@1.1.0", "", {}, "sha512-F8gPlqpP+HwRPMO/8uOu5wjH110+6q4cgJvgJT6vlpy3BEaDIKlTZrgHKZSp/i1InRpVfh4puY/kvL6MxK930A=="], + + "d3-path": ["d3-path@3.1.0", "", {}, "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ=="], + + "d3-quadtree": ["d3-quadtree@3.0.1", "", {}, "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw=="], + + "d3-random": ["d3-random@3.0.1", "", {}, "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ=="], + + "d3-regression": ["d3-regression@1.3.10", "", {}, "sha512-PF8GWEL70cHHWpx2jUQXc68r1pyPHIA+St16muk/XRokETzlegj5LriNKg7o4LR0TySug4nHYPJNNRz/W+/Niw=="], + + "d3-scale": ["d3-scale@4.0.2", "", { "dependencies": { "d3-array": "2.10.0 - 3", "d3-format": "1 - 3", "d3-interpolate": "1.2.0 - 3", "d3-time": "2.1.1 - 3", "d3-time-format": "2 - 4" } }, "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ=="], + + "d3-scale-chromatic": ["d3-scale-chromatic@3.1.0", "", { "dependencies": { "d3-color": "1 - 3", "d3-interpolate": "1 - 3" } }, "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ=="], + + "d3-shape": ["d3-shape@3.2.0", "", { "dependencies": { "d3-path": "^3.1.0" } }, "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA=="], + + "d3-time": ["d3-time@3.1.0", "", { "dependencies": { "d3-array": "2 - 3" } }, "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q=="], + + "d3-time-format": ["d3-time-format@4.1.0", "", { "dependencies": { "d3-time": "1 - 3" } }, "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg=="], + + "d3-timer": ["d3-timer@3.0.1", "", {}, "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA=="], + + "dagre": ["dagre@0.8.5", "", { "dependencies": { "graphlib": "^2.1.8", "lodash": "^4.17.15" } }, "sha512-/aTqmnRta7x7MCCpExk7HQL2O4owCT2h8NT//9I1OQ9vt29Pa0BzSAkR5lwFUcQ7491yVi/3CXU9jQ5o0Mn2Sw=="], + "dayjs": ["dayjs@1.11.13", "", {}, "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg=="], "debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], @@ -333,6 +574,12 @@ "electron-to-chromium": ["electron-to-chromium@1.5.155", "", {}, "sha512-ps5KcGGmwL8VaeJlvlDlu4fORQpv3+GIcF5I3f9tUKUlJ/wsysh6HU8P5L1XWRYeXfA0oJd4PyM8ds8zTFf6Ng=="], + "emojis-list": ["emojis-list@3.0.0", "", {}, "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q=="], + + "enhanced-resolve": ["enhanced-resolve@5.18.1", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" } }, "sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg=="], + + "es-module-lexer": ["es-module-lexer@1.7.0", "", {}, "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA=="], + "esbuild": ["esbuild@0.25.4", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.4", "@esbuild/android-arm": "0.25.4", "@esbuild/android-arm64": "0.25.4", "@esbuild/android-x64": "0.25.4", "@esbuild/darwin-arm64": "0.25.4", "@esbuild/darwin-x64": "0.25.4", "@esbuild/freebsd-arm64": "0.25.4", "@esbuild/freebsd-x64": "0.25.4", "@esbuild/linux-arm": "0.25.4", "@esbuild/linux-arm64": "0.25.4", "@esbuild/linux-ia32": "0.25.4", "@esbuild/linux-loong64": "0.25.4", "@esbuild/linux-mips64el": "0.25.4", "@esbuild/linux-ppc64": "0.25.4", "@esbuild/linux-riscv64": "0.25.4", "@esbuild/linux-s390x": "0.25.4", "@esbuild/linux-x64": "0.25.4", "@esbuild/netbsd-arm64": "0.25.4", "@esbuild/netbsd-x64": "0.25.4", "@esbuild/openbsd-arm64": "0.25.4", "@esbuild/openbsd-x64": "0.25.4", "@esbuild/sunos-x64": "0.25.4", "@esbuild/win32-arm64": "0.25.4", "@esbuild/win32-ia32": "0.25.4", "@esbuild/win32-x64": "0.25.4" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q=="], "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="], @@ -359,6 +606,10 @@ "esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="], + "eventemitter3": ["eventemitter3@5.0.1", "", {}, "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="], + + "events": ["events@3.3.0", "", {}, "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q=="], + "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], "fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="], @@ -367,10 +618,14 @@ "fast-levenshtein": ["fast-levenshtein@2.0.6", "", {}, "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="], + "fast-uri": ["fast-uri@3.0.6", "", {}, "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw=="], + "fastq": ["fastq@1.19.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ=="], "fdir": ["fdir@6.4.4", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg=="], + "fecha": ["fecha@4.2.3", "", {}, "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw=="], + "file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="], "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], @@ -381,24 +636,42 @@ "flatted": ["flatted@3.3.3", "", {}, "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg=="], + "flru": ["flru@1.0.2", "", {}, "sha512-kWyh8ADvHBFz6ua5xYOPnUroZTT/bwWfrCeL0Wj1dzG4/YOmOcfJ99W8dOVyyynJN35rZ9aCOtHChqQovV7yog=="], + "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], "gensync": ["gensync@1.0.0-beta.2", "", {}, "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg=="], + "gl-matrix": ["gl-matrix@3.4.3", "", {}, "sha512-wcCp8vu8FT22BnvKVPjXa/ICBWRq/zjFfdofZy1WSpQZpphblv12/bOQLBC1rMM7SGOFS9ltVmKOHil5+Ml7gA=="], + "glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="], + "glob-to-regexp": ["glob-to-regexp@0.4.1", "", {}, "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw=="], + "globals": ["globals@16.1.0", "", {}, "sha512-aibexHNbb/jiUSObBgpHLj+sIuUmJnYcgXBlrfsiDZ9rt4aF2TFRbyLgZ2iFQuVZ1K5Mx3FVkbKRSgKrbK3K2g=="], + "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], + "graphemer": ["graphemer@1.4.0", "", {}, "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag=="], + "graphlib": ["graphlib@2.1.8", "", { "dependencies": { "lodash": "^4.17.15" } }, "sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A=="], + "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], + "iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="], + "ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="], "import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="], "imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="], + "internmap": ["internmap@2.0.3", "", {}, "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg=="], + + "is-any-array": ["is-any-array@2.0.1", "", {}, "sha512-UtilS7hLRu++wb/WBAw9bNuP1Eg04Ivn1vERJck8zJthEvXCBEBpGR/33u/xLKWEQf95803oalHrVDptcAvFdQ=="], + + "is-arrayish": ["is-arrayish@0.3.2", "", {}, "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="], + "is-buffer": ["is-buffer@1.1.6", "", {}, "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="], "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], @@ -409,6 +682,8 @@ "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], + "jest-worker": ["jest-worker@27.5.1", "", { "dependencies": { "@types/node": "*", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" } }, "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg=="], + "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], "js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="], @@ -417,6 +692,8 @@ "json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="], + "json-parse-even-better-errors": ["json-parse-even-better-errors@2.3.1", "", {}, "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="], + "json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], "json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="], @@ -429,26 +706,48 @@ "levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="], + "loader-runner": ["loader-runner@4.3.0", "", {}, "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg=="], + + "loader-utils": ["loader-utils@2.0.4", "", { "dependencies": { "big.js": "^5.2.2", "emojis-list": "^3.0.0", "json5": "^2.1.2" } }, "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw=="], + "locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="], + "lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="], + "lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="], "lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="], "md5": ["md5@2.3.0", "", { "dependencies": { "charenc": "0.0.2", "crypt": "0.0.2", "is-buffer": "~1.1.6" } }, "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g=="], + "merge-stream": ["merge-stream@2.0.0", "", {}, "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="], + "merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="], "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="], + "mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], + + "mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], + "minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], + "ml-array-max": ["ml-array-max@1.2.4", "", { "dependencies": { "is-any-array": "^2.0.0" } }, "sha512-BlEeg80jI0tW6WaPyGxf5Sa4sqvcyY6lbSn5Vcv44lp1I2GR6AWojfUvLnGTNsIXrZ8uqWmo8VcG1WpkI2ONMQ=="], + + "ml-array-min": ["ml-array-min@1.2.3", "", { "dependencies": { "is-any-array": "^2.0.0" } }, "sha512-VcZ5f3VZ1iihtrGvgfh/q0XlMobG6GQ8FsNyQXD3T+IlstDv85g8kfV0xUG1QPRO/t21aukaJowDzMTc7j5V6Q=="], + + "ml-array-rescale": ["ml-array-rescale@1.3.7", "", { "dependencies": { "is-any-array": "^2.0.0", "ml-array-max": "^1.2.4", "ml-array-min": "^1.2.3" } }, "sha512-48NGChTouvEo9KBctDfHC3udWnQKNKEWN0ziELvY3KG25GR5cA8K8wNVzracsqSW1QEkAXjTNx+ycgAv06/1mQ=="], + + "ml-matrix": ["ml-matrix@6.12.1", "", { "dependencies": { "is-any-array": "^2.0.1", "ml-array-rescale": "^1.3.7" } }, "sha512-TJ+8eOFdp+INvzR4zAuwBQJznDUfktMtOB6g/hUcGh3rcyjxbz4Te57Pgri8Q9bhSQ7Zys4IYOGhFdnlgeB6Lw=="], + "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], "nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], "natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="], + "neo-async": ["neo-async@2.6.2", "", {}, "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw=="], + "node-releases": ["node-releases@2.0.19", "", {}, "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw=="], "optionator": ["optionator@0.9.4", "", { "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.5" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="], @@ -463,18 +762,28 @@ "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], + "pdfast": ["pdfast@0.2.0", "", {}, "sha512-cq6TTu6qKSFUHwEahi68k/kqN2mfepjkGrG9Un70cgdRRKLKY6Rf8P8uvP2NvZktaQZNF3YE7agEkLj0vGK9bA=="], + "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], "picomatch": ["picomatch@4.0.2", "", {}, "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg=="], "postcss": ["postcss@8.5.3", "", { "dependencies": { "nanoid": "^3.3.8", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A=="], + "postcss-value-parser": ["postcss-value-parser@4.2.0", "", {}, "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="], + "prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="], "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="], + "quickselect": ["quickselect@2.0.0", "", {}, "sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw=="], + + "randombytes": ["randombytes@2.1.0", "", { "dependencies": { "safe-buffer": "^5.1.0" } }, "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ=="], + + "rbush": ["rbush@3.0.1", "", { "dependencies": { "quickselect": "^2.0.0" } }, "sha512-XRaVO0YecOpEuIvbhbpTrZgoiI6xBlz6hnlr6EHhd+0x9ase6EmeN+hdwwUaJvLcsFFQ8iWVF1GAK1yB0BWi0w=="], + "rc-cascader": ["rc-cascader@3.34.0", "", { "dependencies": { "@babel/runtime": "^7.25.7", "classnames": "^2.3.1", "rc-select": "~14.16.2", "rc-tree": "~5.13.0", "rc-util": "^5.43.0" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-KpXypcvju9ptjW9FaN2NFcA2QH9E9LHKq169Y0eWtH4e/wHQ5Wh5qZakAgvb8EKZ736WZ3B0zLLOBsrsja5Dag=="], "rc-checkbox": ["rc-checkbox@3.5.0", "", { "dependencies": { "@babel/runtime": "^7.10.1", "classnames": "^2.3.2", "rc-util": "^5.25.2" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-aOAQc3E98HteIIsSqm6Xk2FPKIER6+5vyEFMZfo73TqM+VVAIqOkHoPjgKLqSNtVLWScoaM7vY2ZrGEheI79yg=="], @@ -553,6 +862,8 @@ "react-router": ["react-router@7.6.0", "", { "dependencies": { "cookie": "^1.0.1", "set-cookie-parser": "^2.6.0" }, "peerDependencies": { "react": ">=18", "react-dom": ">=18" }, "optionalPeers": ["react-dom"] }, "sha512-GGufuHIVCJDbnIAXP3P9Sxzq3UUsddG3rrI3ut1q6m0FI6vxVBF3JoPQ38+W/blslLH4a5Yutp8drkEpXoddGQ=="], + "require-from-string": ["require-from-string@2.0.2", "", {}, "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="], + "resize-observer-polyfill": ["resize-observer-polyfill@1.5.1", "", {}, "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg=="], "resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="], @@ -563,28 +874,56 @@ "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="], + "rw": ["rw@1.3.3", "", {}, "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ=="], + + "safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="], + + "safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="], + "scheduler": ["scheduler@0.26.0", "", {}, "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA=="], + "schema-utils": ["schema-utils@4.3.2", "", { "dependencies": { "@types/json-schema": "^7.0.9", "ajv": "^8.9.0", "ajv-formats": "^2.1.1", "ajv-keywords": "^5.1.0" } }, "sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ=="], + "scroll-into-view-if-needed": ["scroll-into-view-if-needed@3.1.0", "", { "dependencies": { "compute-scroll-into-view": "^3.0.2" } }, "sha512-49oNpRjWRvnU8NyGVmUaYG4jtTkNonFZI86MmGRDqBphEK2EXT9gdEUoQPZhuBM8yWHxCWbobltqYO5M4XrUvQ=="], "semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], + "serialize-javascript": ["serialize-javascript@6.0.2", "", { "dependencies": { "randombytes": "^2.1.0" } }, "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g=="], + "set-cookie-parser": ["set-cookie-parser@2.7.1", "", {}, "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ=="], + "shallowequal": ["shallowequal@1.1.0", "", {}, "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ=="], + "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="], + "simple-swizzle": ["simple-swizzle@0.2.2", "", { "dependencies": { "is-arrayish": "^0.3.1" } }, "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg=="], + + "source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], + "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], + "source-map-support": ["source-map-support@0.5.21", "", { "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w=="], + "string-convert": ["string-convert@0.2.1", "", {}, "sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A=="], "strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="], + "styled-components": ["styled-components@6.1.18", "", { "dependencies": { "@emotion/is-prop-valid": "1.2.2", "@emotion/unitless": "0.8.1", "@types/stylis": "4.2.5", "css-to-react-native": "3.2.0", "csstype": "3.1.3", "postcss": "8.4.49", "shallowequal": "1.1.0", "stylis": "4.3.2", "tslib": "2.6.2" }, "peerDependencies": { "react": ">= 16.8.0", "react-dom": ">= 16.8.0" } }, "sha512-Mvf3gJFzZCkhjY2Y/Fx9z1m3dxbza0uI9H1CbNZm/jSHCojzJhQ0R7bByrlFJINnMzz/gPulpoFFGymNwrsMcw=="], + "stylis": ["stylis@4.3.6", "", {}, "sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ=="], "supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], + "svg-path-parser": ["svg-path-parser@1.1.0", "", {}, "sha512-jGCUqcQyXpfe38R7RFfhrMyfXcBmpMNJI/B+4CE9/Unkh98UporAc461GTthv+TVDuZXsBx7/WiwJb1Oh4tt4A=="], + + "tapable": ["tapable@2.2.2", "", {}, "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg=="], + + "terser": ["terser@5.39.2", "", { "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.14.0", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, "bin": { "terser": "bin/terser" } }, "sha512-yEPUmWve+VA78bI71BW70Dh0TuV4HHd+I5SHOAfS1+QBOmvmCiiffgjR8ryyEd3KIfvPGFqoADt8LdQ6XpXIvg=="], + + "terser-webpack-plugin": ["terser-webpack-plugin@5.3.14", "", { "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", "jest-worker": "^27.4.5", "schema-utils": "^4.3.0", "serialize-javascript": "^6.0.2", "terser": "^5.31.1" }, "peerDependencies": { "webpack": "^5.1.0" } }, "sha512-vkZjpUjb6OMS7dhV+tILUW6BhpDR7P2L/aQSAv+Uwk+m8KATX9EccViHTJR2qDtACKPIYndLGCyl3FMo+r2LMw=="], + "throttle-debounce": ["throttle-debounce@5.0.2", "", {}, "sha512-B71/4oyj61iNH0KeCamLuE2rmKuTO5byTOSVwECM5FA7TiAiAW+UqTKZ9ERueC4qvgSttUhdmq1mXC3kJqGX7A=="], "tinyglobby": ["tinyglobby@0.2.13", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw=="], @@ -595,12 +934,16 @@ "ts-api-utils": ["ts-api-utils@2.1.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ=="], + "tslib": ["tslib@2.6.2", "", {}, "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="], + "type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="], "typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="], "typescript-eslint": ["typescript-eslint@8.32.1", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.32.1", "@typescript-eslint/parser": "8.32.1", "@typescript-eslint/utils": "8.32.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-D7el+eaDHAmXvrZBy1zpzSNIRqnCOrkwTgZxTu3MUqRWk8k0q9m9Ho4+vPf7iHtgUfrK/o8IZaEApsxPlHTFCg=="], + "undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="], + "update-browserslist-db": ["update-browserslist-db@1.1.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw=="], "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="], @@ -609,14 +952,28 @@ "vite": ["vite@6.3.5", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ=="], + "watchpack": ["watchpack@2.4.4", "", { "dependencies": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" } }, "sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA=="], + + "webpack": ["webpack@5.99.9", "", { "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "@webassemblyjs/ast": "^1.14.1", "@webassemblyjs/wasm-edit": "^1.14.1", "@webassemblyjs/wasm-parser": "^1.14.1", "acorn": "^8.14.0", "browserslist": "^4.24.0", "chrome-trace-event": "^1.0.2", "enhanced-resolve": "^5.17.1", "es-module-lexer": "^1.2.1", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.2.11", "json-parse-even-better-errors": "^2.3.1", "loader-runner": "^4.2.0", "mime-types": "^2.1.27", "neo-async": "^2.6.2", "schema-utils": "^4.3.2", "tapable": "^2.1.1", "terser-webpack-plugin": "^5.3.11", "watchpack": "^2.4.1", "webpack-sources": "^3.2.3" }, "bin": { "webpack": "bin/webpack.js" } }, "sha512-brOPwM3JnmOa+7kd3NsmOUOwbDAj8FT9xDsG3IW0MgbN9yZV7Oi/s/+MNQ/EcSMqw7qfoRyXPoeEWT8zLVdVGg=="], + + "webpack-sources": ["webpack-sources@3.3.0", "", {}, "sha512-77R0RDmJfj9dyv5p3bM5pOHa+X8/ZkO9c7kpDstigkC4nIDobadsfSGCwB4bKhMVxqAok8tajaoR8rirM7+VFQ=="], + "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], "word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="], + "workerize-loader": ["workerize-loader@2.0.2", "", { "dependencies": { "loader-utils": "^2.0.0" }, "peerDependencies": { "webpack": "*" } }, "sha512-HoZ6XY4sHWxA2w0WpzgBwUiR3dv1oo7bS+oCwIpb6n54MclQ/7KXdXsVIChTCygyuHtVuGBO1+i3HzTt699UJQ=="], + "yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="], "yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="], + "@ant-design/plots/@ant-design/charts-util": ["@ant-design/charts-util@0.0.1", "", { "dependencies": { "lodash": "^4.17.21" }, "peerDependencies": { "react": ">=16.8.4", "react-dom": ">=16.8.4" } }, "sha512-zz9aCD8z90gzLm3XK17jyFdVtmpLrFApvexzIl5n9+TrxvIgrmOIqemlvx6QvzkmmXcOA6VIEJGzqQBSBAq55A=="], + + "@antv/algorithm/@antv/util": ["@antv/util@2.0.17", "", { "dependencies": { "csstype": "^3.0.8", "tslib": "^2.0.3" } }, "sha512-o6I9hi5CIUvLGDhth0RxNSFDRwXeywmt6ExR4+RmVAzIi48ps6HUy+svxOCayvrPBN37uE6TAc2KDofRo0nK9Q=="], + + "@antv/coord/@antv/util": ["@antv/util@2.0.17", "", { "dependencies": { "csstype": "^3.0.8", "tslib": "^2.0.3" } }, "sha512-o6I9hi5CIUvLGDhth0RxNSFDRwXeywmt6ExR4+RmVAzIi48ps6HUy+svxOCayvrPBN37uE6TAc2KDofRo0nK9Q=="], + "@babel/traverse/globals": ["globals@11.12.0", "", {}, "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="], "@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], @@ -631,10 +988,32 @@ "@typescript-eslint/typescript-estree/semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="], + "ajv-formats/ajv": ["ajv@8.17.1", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="], + "fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], + "jest-worker/supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="], + "micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], + "schema-utils/ajv": ["ajv@8.17.1", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="], + + "styled-components/@emotion/unitless": ["@emotion/unitless@0.8.1", "", {}, "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ=="], + + "styled-components/postcss": ["postcss@8.4.49", "", { "dependencies": { "nanoid": "^3.3.7", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA=="], + + "styled-components/stylis": ["stylis@4.3.2", "", {}, "sha512-bhtUjWd/z6ltJiQwg0dUfxEJ+W+jdqQd8TbWLWyeIJHlnsqmGLRFFd8e5mA0AZi/zx90smXRlN66YMTcaSFifg=="], + + "terser/commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="], + + "webpack/eslint-scope": ["eslint-scope@5.1.1", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" } }, "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw=="], + "@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], + + "ajv-formats/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="], + + "schema-utils/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="], + + "webpack/eslint-scope/estraverse": ["estraverse@4.3.0", "", {}, "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw=="], } } diff --git a/Web/package.json b/Web/package.json index bfc1e24..e463de4 100644 --- a/Web/package.json +++ b/Web/package.json @@ -10,6 +10,7 @@ "preview": "vite preview" }, "dependencies": { + "@ant-design/charts": "^2.3.0", "@ant-design/v5-patch-for-react-19": "^1.0.3", "@types/md5": "^2.3.5", "antd": "^5.24.9", diff --git a/Web/src/App.tsx b/Web/src/App.tsx index dab5430..cabb9dd 100644 --- a/Web/src/App.tsx +++ b/Web/src/App.tsx @@ -6,9 +6,10 @@ import Register from './pages/register/Index'; import { isAuthenticated } from './api'; import type { JSX } from 'react'; import { ConfigProvider } from 'antd'; -import routes from './config/routeConfig'; -import { AuthProvider } from './api/AuthContext'; // 导入 AuthProvider +import { getMainRoutes, getAdminRoutes } from './routes'; +import { AuthProvider } from './auth/AuthContext'; import AnonymousPage from './pages/anonymous/Index'; +import AdminLayout from './layouts/AdminLayout'; const PrivateRoute = ({ children }: { children: JSX.Element }) => { return isAuthenticated() ? children : ; @@ -45,9 +46,12 @@ const customTheme = { }; function App() { + const mainRoutes = getMainRoutes(); + const adminRoutes = getAdminRoutes(); + return ( - - + + } /> @@ -59,14 +63,32 @@ function App() { }> - {routes.map((route) => ( - + {mainRoutes.map((route) => ( + + ))} + + + + + + }> + {adminRoutes.map((route) => ( + ))} - - + + ); } diff --git a/Web/src/api/index.ts b/Web/src/api/index.ts index ce67681..ce358b2 100644 --- a/Web/src/api/index.ts +++ b/Web/src/api/index.ts @@ -57,3 +57,30 @@ export { restoreConfigs } from './configApi'; +// 导出UserManagement API +export { + getUsers, + getUserById, + createUser, + updateUser, + deleteUser, + batchDeleteUsers +} from './userManagementApi'; + +// 导出PictureManagement API +export { + getManagementPictures, + getManagementPictureById, + deleteManagementPicture, + batchDeleteManagementPictures, + getManagementPicturesByUserId +} from './pictureManagementApi'; + +// 导出向量数据库 API +export { + getCurrentVectorDb, + switchVectorDb, + clearVectors, + rebuildVectors +} from './vectorDbApi'; + diff --git a/Web/src/api/pictureManagementApi.ts b/Web/src/api/pictureManagementApi.ts new file mode 100644 index 0000000..af74a33 --- /dev/null +++ b/Web/src/api/pictureManagementApi.ts @@ -0,0 +1,58 @@ +import { fetchApi } from './fetchClient'; +import { + type BaseResult, + type PaginatedResult, + type PictureResponse, + type BatchDeleteResult +} from './types'; + +// 获取图片列表 +export const getManagementPictures = async ( + page: number = 1, + pageSize: number = 10 +): Promise> => { + const response = await fetchApi(`/management/picture/get_pictures?page=${page}&pageSize=${pageSize}`); + return response as PaginatedResult; +}; + +// 根据ID获取单张图片 +export const getManagementPictureById = async (id: number): Promise> => { + return fetchApi( + `/management/picture/get_picture/${id}`, + { method: 'GET' } + ); +}; + +// 删除图片 +export const deleteManagementPicture = async (id: number): Promise> => { + return fetchApi( + '/management/picture/delete_picture', + { + method: 'POST', + body: JSON.stringify(id) + } + ); +}; + +// 批量删除图片 +export const batchDeleteManagementPictures = async ( + ids: number[] +): Promise> => { + return fetchApi( + '/management/picture/batch_delete_pictures', + { + method: 'POST', + body: JSON.stringify(ids) + } + ); +}; + +// 根据用户ID获取图片 +export const getManagementPicturesByUserId = async ( + userId: number, + page: number = 1, + pageSize: number = 10 +): Promise> => { + const response = await fetchApi(`/management/picture/get_pictures_by_user/${userId}?page=${page}&pageSize=${pageSize}`); + return response as PaginatedResult; +}; diff --git a/Web/src/api/types.ts b/Web/src/api/types.ts index 7d5374a..f2db0ac 100644 --- a/Web/src/api/types.ts +++ b/Web/src/api/types.ts @@ -227,3 +227,47 @@ export interface UpdatePictureRequest { description?: string; tags?: string[]; } + +// 用户管理相关类型 +export interface UserResponse { + id: number; + userName: string; + email: string; + role: string; + createdAt: Date; + lastLoginAt?: Date; +} + +// 管理员创建用户请求 +export interface CreateUserRequest { + userName: string; + email: string; + password: string; + role: string; +} + +// 管理员更新用户请求 +export interface AdminUpdateUserRequest { + id: number; + userName?: string; + email?: string; + role?: string; +} + +// 批量删除结果 +export interface BatchDeleteResult { + successCount: number; + failedCount: number; + failedIds?: number[]; +} + +export type VectorDbType = "InMemory" | "Qdrant"; + +export const VectorDbType = { + InMemory: "InMemory" as VectorDbType, + Qdrant: "Qdrant" as VectorDbType, +}; + +export interface VectorDbInfo { + type: string; +} diff --git a/Web/src/api/userManagementApi.ts b/Web/src/api/userManagementApi.ts new file mode 100644 index 0000000..8144ddd --- /dev/null +++ b/Web/src/api/userManagementApi.ts @@ -0,0 +1,76 @@ +import { fetchApi } from './fetchClient'; +import { + type BaseResult, + type PaginatedResult, + type UserResponse, + type CreateUserRequest, + type AdminUpdateUserRequest, + type BatchDeleteResult +} from './types'; + +// 获取用户列表 +export const getUsers = async ( + page: number = 1, + pageSize: number = 10 +): Promise> => { + const response = await fetchApi(`/management/user/get_users?page=${page}&pageSize=${pageSize}`); + return response as PaginatedResult; +}; + +// 根据ID获取单个用户 +export const getUserById = async (id: number): Promise> => { + return fetchApi( + `/management/user/get_user/${id}`, + { method: 'GET' } + ); +}; + +// 创建用户 +export const createUser = async ( + userData: CreateUserRequest +): Promise> => { + return fetchApi( + '/management/user/create_user', + { + method: 'POST', + body: JSON.stringify(userData) + } + ); +}; + +// 更新用户 +export const updateUser = async ( + userData: AdminUpdateUserRequest +): Promise> => { + return fetchApi( + '/management/user/update_user', + { + method: 'POST', + body: JSON.stringify(userData) + } + ); +}; + +// 删除用户 +export const deleteUser = async (id: number): Promise> => { + return fetchApi( + '/management/user/delete_user', + { + method: 'POST', + body: JSON.stringify(id) + } + ); +}; + +// 批量删除用户 +export const batchDeleteUsers = async ( + ids: number[] +): Promise> => { + return fetchApi( + '/management/user/batch_delete_users', + { + method: 'POST', + body: JSON.stringify(ids) + } + ); +}; diff --git a/Web/src/api/vectorDbApi.ts b/Web/src/api/vectorDbApi.ts new file mode 100644 index 0000000..bb1cfab --- /dev/null +++ b/Web/src/api/vectorDbApi.ts @@ -0,0 +1,61 @@ +import { type BaseResult, type VectorDbInfo, VectorDbType } from './types'; +import { fetchApi } from './fetchClient'; + +// 获取当前向量数据库类型 +export const getCurrentVectorDb = async (): Promise> => { + try { + return await fetchApi('/management/system/vector-db/current'); + } catch (error: any) { + return { + success: false, + message: `获取当前向量数据库失败: ${error.message}`, + code: 500 + }; + } +}; + +// 切换向量数据库类型 +export const switchVectorDb = async (type: VectorDbType): Promise> => { + try { + return await fetchApi('/management/system/vector-db/switch', { + method: 'POST', + body: JSON.stringify({ type }), + }); + } catch (error: any) { + return { + success: false, + message: `切换向量数据库失败: ${error.message}`, + code: 500 + }; + } +}; + +// 清空向量数据库 +export const clearVectors = async (): Promise> => { + try { + return await fetchApi('/management/system/vector-db/clear', { + method: 'DELETE' + }); + } catch (error: any) { + return { + success: false, + message: `清空向量数据库失败: ${error.message}`, + code: 500 + }; + } +}; + +// 重建向量数据库 +export const rebuildVectors = async (): Promise> => { + try { + return await fetchApi('/management/system/vector-db/rebuild', { + method: 'POST' + }); + } catch (error: any) { + return { + success: false, + message: `重建向量数据库失败: ${error.message}`, + code: 500 + }; + } +}; diff --git a/Web/src/api/AuthContext.tsx b/Web/src/auth/AuthContext.tsx similarity index 95% rename from Web/src/api/AuthContext.tsx rename to Web/src/auth/AuthContext.tsx index ab6d834..01a81bf 100644 --- a/Web/src/api/AuthContext.tsx +++ b/Web/src/auth/AuthContext.tsx @@ -1,7 +1,7 @@ import React, { createContext, useState, useEffect, useContext, useCallback } from 'react'; -import { getCurrentUser, isAuthenticated, clearAuthData, getStoredUser } from './index'; -import type { UserProfile } from './types'; -import { UserRole } from './types'; +import { getCurrentUser, isAuthenticated, clearAuthData, getStoredUser } from '../api/index'; +import type { UserProfile } from '../api/types'; +import { UserRole } from '../api/types'; interface AuthContextType { user: UserProfile | null; @@ -27,7 +27,6 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children const [user, setUser] = useState(null); const [loading, setLoading] = useState(true); const [authError, setAuthError] = useState(null); - const refreshUser = useCallback(async () => { setLoading(true); setAuthError(null); diff --git a/Web/src/components/image/ImageGrid.tsx b/Web/src/components/image/ImageGrid.tsx index 99ab512..bccdb7c 100644 --- a/Web/src/components/image/ImageGrid.tsx +++ b/Web/src/components/image/ImageGrid.tsx @@ -10,7 +10,7 @@ import ImageViewer from './ImageViewer'; import ShareImageDialog from './ShareImageDialog'; import EditImageDialog from './EditImageDialog'; import './ImageGrid.css'; -import { useAuth } from '../../api/AuthContext'; +import { useAuth } from '../../auth/AuthContext'; const { Text } = Typography; diff --git a/Web/src/layouts/AdminLayout.tsx b/Web/src/layouts/AdminLayout.tsx new file mode 100644 index 0000000..4cb65f5 --- /dev/null +++ b/Web/src/layouts/AdminLayout.tsx @@ -0,0 +1,208 @@ +import { useState, useEffect, useCallback, useMemo } from 'react'; +import { Outlet, useNavigate, useLocation, matchPath, Navigate } from 'react-router'; +import { Layout, theme, message } from 'antd'; +import { clearAuthData, isAuthenticated } from '../api'; +import useIsMobile from '../hooks/useIsMobile'; +import { useAuth } from '../auth/AuthContext'; +import Sidebar from './components/Sidebar'; +import Header from './components/Header'; +import Footer from './components/Footer'; +import { UserRole } from '../api/types'; +import { getAdminRoutes, type RouteConfig } from '../routes'; + +const { Content } = Layout; + +function AdminLayout() { + const { refreshUser, hasRole, user, loading } = useAuth(); + const isMobile = useIsMobile(); + const [collapsed, setCollapsed] = useState(isMobile); + const [currentRouteData, setCurrentRouteData] = useState<{ + routeInfo: RouteConfig | undefined; + params: Record; + title?: string; + }>({ + routeInfo: undefined, + params: {} + }); + + const navigate = useNavigate(); + const location = useLocation(); + + const routes = useMemo(() => getAdminRoutes(), []); + + const headerRouteData = useMemo(() => ({ + routeInfo: currentRouteData.routeInfo, + params: currentRouteData.params, + title: (currentRouteData.routeInfo?.label || '') + }), [currentRouteData]); + + const { + token: { colorBgContainer }, + } = theme.useToken(); + + const findCurrentRoute = useCallback(() => { + const pathname = location.pathname; + const adminPath = pathname.replace(/^\/admin\/?/, ''); + + if (adminPath === '') { + const defaultRoute = routes.find(route => route.path === ''); + if (defaultRoute) { + return { + routeInfo: defaultRoute, + params: {} + }; + } + } + + // 查找精确匹配的路由 + for (const route of routes) { + const match = matchPath( + { path: route.path, end: true }, + adminPath + ); + + if (match) { + return { + routeInfo: route, + params: Object.fromEntries( + Object.entries(match.params || {}).filter( + ([, value]) => value !== undefined + ) + ) as Record + }; + } + } + + // 查找包含参数的路由 + for (const route of routes) { + if (route.path.includes(':')) { + const basePath = route.path.split('/:')[0]; + if (adminPath.startsWith(basePath)) { + const match = matchPath( + { path: route.path, end: false }, + adminPath + ); + + if (match) { + return { + routeInfo: route, + params: Object.fromEntries( + Object.entries(match.params || {}).filter( + ([, value]) => value !== undefined + ) + ) as Record + }; + } + } + } + } + + return { + routeInfo: undefined, + params: {} + }; + }, [location.pathname, routes]); + + useEffect(() => { + if (!isAuthenticated()) { + navigate('/login'); + return; + } + + if (!user) { + refreshUser(); + } + }, [navigate, refreshUser, user]); + + useEffect(() => { + if (!loading && user && !hasRole(UserRole.Administrator)) { + message.error('您没有权限访问管理后台'); + navigate('/'); + } + }, [user, hasRole, navigate, loading]); + useEffect(() => { + const routeData = findCurrentRoute(); + setCurrentRouteData(routeData); + }, [location.pathname, findCurrentRoute]); + useEffect(() => { + setCollapsed(isMobile); + }, [isMobile]); + + // 退出登录处理 + const handleLogout = () => { + clearAuthData(); + navigate('/login'); + }; + + const toggleCollapsed = () => { + setCollapsed(!collapsed); + }; + + // 加载状态 + if (loading) { + return
+ 加载中... +
; + } + + // 权限检查 + if (user && !hasRole(UserRole.Administrator)) { + return ; + } + + return ( + + {/* 侧边栏组件 */} + + + + {/* 顶部导航栏组件 */} +
+ + {/* 主要内容区 */} + +
+ {/* 渲染子路由组件 */} + +
+
+ {/* 页脚组件 */} +