Files
Foxel/Services/Media/AlbumService.cs

352 lines
12 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System.Security.Claims;
using Foxel.Models;
using Foxel.Models.DataBase;
using Foxel.Models.Response.Album;
using Microsoft.EntityFrameworkCore;
using Foxel.Services.Mapping; // 添加 using
namespace Foxel.Services.Media;
public class AlbumService(
IDbContextFactory<MyDbContext> contextFactory,
IHttpContextAccessor httpContextAccessor,
IMappingService mappingService) // 注入新的映射服务
: IAlbumService
{
public async Task<PaginatedResult<AlbumResponse>> GetAlbumsAsync(int page = 1, int pageSize = 10, int? userId = null)
{
if (page < 1) page = 1;
if (pageSize < 1) pageSize = 10;
await using var dbContext = await contextFactory.CreateDbContextAsync();
// 构建查询
IQueryable<Album> query = dbContext.Albums
.Include(a => a.User)
.Include(a => a.CoverPicture) // 确保包含封面图片
.Include(a => a.Pictures) // 确保包含图片集合以计算 PictureCount
.OrderByDescending(a => a.CreatedAt);
// 如果指定了用户ID则只获取该用户的相册
if (userId.HasValue)
{
query = query.Where(a => a.UserId == userId.Value);
}
// 获取总数和分页数据
var totalCount = await query.CountAsync();
var albums = await query
// .Include(a => a.CoverPicture) // 已在上面包含
.Skip((page - 1) * pageSize)
.Take(pageSize)
.ToListAsync();
// 获取每个相册中的图片数量 - 不再需要MapAlbumToResponse 会处理
// var albumIds = albums.Select(a => a.Id).ToList();
// var albumPictureCounts = await dbContext.Pictures
// .Where(p => p.AlbumId != null && albumIds.Contains(p.AlbumId.Value))
// .GroupBy(p => p.AlbumId)
// .Select(g => new { AlbumId = g.Key, Count = g.Count() })
// .ToDictionaryAsync(x => x.AlbumId!.Value, x => x.Count);
// 转换为响应模型
var albumResponses = albums.Select(mappingService.MapAlbumToResponse).ToList();
// var albumResponses = albums.Select(a => new AlbumResponse
// {
// Id = a.Id,
// Name = a.Name,
// Description = a.Description,
// PictureCount = albumPictureCounts.GetValueOrDefault(a.Id, 0), // 使用 MapAlbumToResponse 后不再需要
// UserId = a.UserId,
// Username = a.User.UserName,
// CreatedAt = a.CreatedAt,
// UpdatedAt = a.UpdatedAt
// }).ToList();
return new PaginatedResult<AlbumResponse>
{
Data = albumResponses,
Page = page,
PageSize = pageSize,
TotalCount = totalCount
};
}
public async Task<AlbumResponse> GetAlbumByIdAsync(int id)
{
await using var dbContext = await contextFactory.CreateDbContextAsync();
var album = await dbContext.Albums
.Include(a => a.User)
.Include(a => a.CoverPicture) // 确保包含封面图片
.Include(a => a.Pictures) // 确保包含图片集合以计算 PictureCount
.FirstOrDefaultAsync(a => a.Id == id);
if (album == null)
throw new KeyNotFoundException($"找不到ID为{id}的相册");
// 获取相册中图片的数量 - 不再需要
// var pictureCount = await dbContext.Pictures
// .Where(p => p.AlbumId == id)
// .CountAsync();
// 转换为响应模型
return mappingService.MapAlbumToResponse(album);
// var response = new AlbumResponse
// {
// Id = album.Id,
// Name = album.Name,
// Description = album.Description,
// PictureCount = pictureCount, // 使用 MapAlbumToResponse 后不再需要
// UserId = album.UserId,
// Username = album.User.UserName,
// CreatedAt = album.CreatedAt,
// UpdatedAt = album.UpdatedAt
// };
//
// return response;
}
public async Task<AlbumResponse> CreateAlbumAsync(string name, string? description, int userId, int? coverPictureId)
{
if (string.IsNullOrWhiteSpace(name))
throw new ArgumentException("相册名称不能为空", nameof(name));
await using var dbContext = await contextFactory.CreateDbContextAsync();
// 检查用户是否存在
var user = await dbContext.Users.FindAsync(userId);
if (user == null)
throw new KeyNotFoundException($"找不到ID为{userId}的用户");
// 创建新相册
var album = new Album
{
Name = name.Trim(),
Description = description?.Trim() ?? string.Empty,
UserId = userId,
// User = user, // EF Core 会自动关联
CreatedAt = DateTime.UtcNow,
UpdatedAt = DateTime.UtcNow,
CoverPictureId = coverPictureId
};
dbContext.Albums.Add(album);
await dbContext.SaveChangesAsync();
// 重新加载创建的相册以包含导航属性,用于 MapAlbumToResponse
var createdAlbum = await dbContext.Albums
.Include(a => a.User)
.Include(a => a.CoverPicture)
.Include(a => a.Pictures)
.FirstAsync(a => a.Id == album.Id);
// 转换为响应模型
return mappingService.MapAlbumToResponse(createdAlbum);
// return new AlbumResponse
// {
// Id = album.Id,
// Name = album.Name,
// Description = album.Description,
// PictureCount = 0, // MapAlbumToResponse 会处理
// UserId = album.UserId,
// Username = user.UserName, // MapAlbumToResponse 会处理
// CreatedAt = album.CreatedAt,
// UpdatedAt = album.UpdatedAt
// };
}
public async Task<AlbumResponse> UpdateAlbumAsync(int id, string name, string? description, int? userId = null, int? coverPictureId = null)
{
if (string.IsNullOrWhiteSpace(name))
throw new ArgumentException("相册名称不能为空", nameof(name));
await using var dbContext = await contextFactory.CreateDbContextAsync();
// 获取相册
var album = await dbContext.Albums
// .Include(a => a.User) // 将在更新后重新加载
// .Include(a => a.Pictures) // 将在更新后重新加载
.FirstOrDefaultAsync(a => a.Id == id);
if (album == null)
throw new KeyNotFoundException($"找不到ID为{id}的相册");
if (!userId.HasValue) // userId 仍然需要用于权限检查
throw new ArgumentException("无效的用户ID", nameof(userId));
if (album.UserId != userId.Value)
{
throw new UnauthorizedAccessException("您没有权限更新此相册");
}
// 更新相册信息
album.Name = name.Trim();
album.Description = description?.Trim() ?? album.Description;
album.UpdatedAt = DateTime.UtcNow;
album.CoverPictureId = coverPictureId;
await dbContext.SaveChangesAsync();
// 重新加载更新后的相册以包含导航属性
var updatedAlbum = await dbContext.Albums
.Include(a => a.User)
.Include(a => a.CoverPicture)
.Include(a => a.Pictures)
.FirstAsync(a => a.Id == album.Id);
// 转换为响应模型
return mappingService.MapAlbumToResponse(updatedAlbum);
// return new AlbumResponse
// {
// Id = album.Id,
// Name = album.Name,
// Description = album.Description,
// PictureCount = album.Pictures?.Count ?? 0, // MapAlbumToResponse 会处理
// UserId = album.UserId,
// Username = album.User.UserName, // MapAlbumToResponse 会处理
// CreatedAt = album.CreatedAt,
// UpdatedAt = album.UpdatedAt
// };
}
public async Task<bool> DeleteAlbumAsync(int id)
{
await using var dbContext = await contextFactory.CreateDbContextAsync();
var album = await dbContext.Albums.FindAsync(id);
if (album == null)
return false;
// 先找出所有属于这个相册的图片
var pictures = await dbContext.Pictures
.Where(p => p.AlbumId == id)
.ToListAsync();
// 将这些图片的AlbumId设置为null
foreach (var picture in pictures)
{
picture.AlbumId = null;
picture.Album = null;
}
// 保存图片更改
await dbContext.SaveChangesAsync();
// 然后删除相册
dbContext.Albums.Remove(album);
await dbContext.SaveChangesAsync();
return true;
}
public async Task<bool> AddPictureToAlbumAsync(int albumId, int pictureId)
{
await using var dbContext = await contextFactory.CreateDbContextAsync();
// 获取相册和图片
var album = await dbContext.Albums.FindAsync(albumId);
if (album == null)
throw new KeyNotFoundException($"找不到ID为{albumId}的相册");
var picture = await dbContext.Pictures.FindAsync(pictureId);
if (picture == null)
throw new KeyNotFoundException($"找不到ID为{pictureId}的图片");
// 将图片添加到相册
picture.AlbumId = albumId;
picture.Album = album;
await dbContext.SaveChangesAsync();
return true;
}
public async Task<bool> RemovePictureFromAlbumAsync(int albumId, int pictureId)
{
await using var dbContext = await contextFactory.CreateDbContextAsync();
// 获取图片
var picture = await dbContext.Pictures
.FirstOrDefaultAsync(p => p.Id == pictureId && p.AlbumId == albumId);
if (picture == null)
throw new KeyNotFoundException($"在相册中找不到ID为{pictureId}的图片");
// 从相册中移除图片
picture.AlbumId = null;
picture.Album = null;
await dbContext.SaveChangesAsync();
return true;
}
public async Task<bool> AddPicturesToAlbumAsync(int albumId, List<int> pictureIds)
{
await using var dbContext = await contextFactory.CreateDbContextAsync();
var album = await dbContext.Albums.FindAsync(albumId)
?? throw new KeyNotFoundException("相册不存在");
// 检查是否有权限修改此相册
var currentUser = httpContextAccessor.HttpContext?.User;
if (currentUser != null)
{
var userId = int.Parse(currentUser.FindFirst(ClaimTypes.NameIdentifier)?.Value ?? "0");
if (album.UserId != userId)
{
throw new UnauthorizedAccessException("您没有权限修改此相册");
}
}
var successCount = 0;
foreach (var pictureId in pictureIds)
{
var picture = await dbContext.Pictures.FindAsync(pictureId);
if (picture == null) continue; // 跳过不存在的图片
// 直接更新 Picture 的 AlbumId
if (picture.AlbumId != albumId)
{
picture.AlbumId = albumId;
successCount++;
}
}
if (successCount > 0)
{
await dbContext.SaveChangesAsync();
return true;
}
return false;
}
public async Task<bool> SetAlbumCoverAsync(int albumId, int pictureId, int userId)
{
await using var dbContext = await contextFactory.CreateDbContextAsync();
var album = await dbContext.Albums.FirstOrDefaultAsync(a => a.Id == albumId);
if (album == null)
throw new KeyNotFoundException($"找不到ID为 {albumId} 的相册");
// 权限检查:只有相册所有者可以设置封面
if (album.UserId != userId)
throw new UnauthorizedAccessException("您没有权限修改此相册的封面");
var picture = await dbContext.Pictures.FirstOrDefaultAsync(p => p.Id == pictureId);
if (picture == null)
throw new KeyNotFoundException($"找不到ID为 {pictureId} 的图片");
// 确保图片属于该相册
if (picture.AlbumId != albumId)
throw new InvalidOperationException($"图片 {pictureId} 不属于相册 {albumId}");
album.CoverPictureId = pictureId;
album.UpdatedAt = DateTime.UtcNow;
await dbContext.SaveChangesAsync();
return true;
}
}