feat: 新增宠物进化分组接口、OSS图片搬运功能及配置更新
1. 新增皮肤按进化阶段分组的输出DTO 2. 新增宠物相关便捷查询接口并实现对应控制器 3. 新增OSS图片搬运辅助类,实现临时文件迁移逻辑 4. 为商品、宠物相关服务添加OSS图片自动迁移功能 5. 调整微信授权同步逻辑移除异步等待 6. 更新配置文件中的微信密钥和OSS存储信息 7. 注册SDK服务到DI容器
This commit is contained in:
@ -1,4 +1,5 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using QYZH.InteractiveMagazine.Infrastructure.OSS;
|
||||
using QYZH.InteractiveMagazine.IService;
|
||||
using QYZH.InteractiveMagazine.Models.Common;
|
||||
using QYZH.InteractiveMagazine.Models.Dto;
|
||||
@ -20,9 +21,11 @@ public class PetService(
|
||||
BaseRepository<PetEvolution> petEvolutionRepository,
|
||||
BaseRepository<PetSkinImage> petSkinImageRepository,
|
||||
BaseRepository<PetSkin> petSkinRepository,
|
||||
OssService ossService,
|
||||
ILogger<PetService> logger)
|
||||
: BaseRepository<UserPet>, IPetService
|
||||
{
|
||||
private OssImageHelper CreateImageHelper() => new(ossService, logger);
|
||||
/// <summary>
|
||||
/// 获取用户宠物信息(含当前形态名称、皮肤图片序列)
|
||||
/// </summary>
|
||||
@ -442,6 +445,8 @@ public class PetService(
|
||||
// 3. 为该阶段创建默认皮肤图片
|
||||
if (evoInput.Images != null && evoInput.Images.Count > 0)
|
||||
{
|
||||
var helper = CreateImageHelper();
|
||||
|
||||
foreach (var imgInput in evoInput.Images.OrderBy(i => i.SortOrder))
|
||||
{
|
||||
var skinImage = new PetSkinImage
|
||||
@ -460,6 +465,14 @@ public class PetService(
|
||||
|
||||
await petSkinImageRepository.InsertAsync(skinImage);
|
||||
|
||||
// 搬运图片到正式目录
|
||||
if (OssImageHelper.IsTempImage(skinImage.ImageUrl))
|
||||
{
|
||||
skinImage.ImageUrl = await helper.MoveToFormalAsync(
|
||||
skinImage.ImageUrl, $"pet/template/{template.Id}/stage/{evolution.Id}");
|
||||
await petSkinImageRepository.UpdateAsync(skinImage);
|
||||
}
|
||||
|
||||
// 记录初始阶段的封面图
|
||||
if (previousEvolution == null
|
||||
&& imgInput.Type == PetSkinImageTypeEnum.Cover.ToString()
|
||||
@ -850,6 +863,14 @@ public class PetService(
|
||||
if (!result)
|
||||
throw new BusinessException("创建皮肤失败", 500);
|
||||
|
||||
// 搬运封面图到正式目录
|
||||
if (OssImageHelper.IsTempImage(skin.CoverImageUrl))
|
||||
{
|
||||
var helper = CreateImageHelper();
|
||||
skin.CoverImageUrl = await helper.MoveToFormalAsync(skin.CoverImageUrl, $"pet/skin/{skin.Id}");
|
||||
await petSkinRepository.UpdateAsync(skin);
|
||||
}
|
||||
|
||||
logger.LogInformation("创建皮肤成功,Id: {Id}, Name: {Name}", skin.Id, skin.Name);
|
||||
return BuildSkinOutput(skin, null);
|
||||
}
|
||||
@ -872,7 +893,16 @@ public class PetService(
|
||||
skin.Rarity = input.Rarity;
|
||||
skin.SortOrder = input.SortOrder;
|
||||
skin.Type = Enum.Parse<PetSkinTypeEnum>(input.Type, true);
|
||||
skin.CoverImageUrl = input.CoverImageUrl;
|
||||
|
||||
// 搬运封面图到正式目录
|
||||
var newCoverUrl = input.CoverImageUrl;
|
||||
if (OssImageHelper.IsTempImage(newCoverUrl))
|
||||
{
|
||||
var helper = CreateImageHelper();
|
||||
newCoverUrl = await helper.MoveToFormalAsync(newCoverUrl, $"pet/skin/{skin.Id}");
|
||||
}
|
||||
skin.CoverImageUrl = newCoverUrl;
|
||||
|
||||
skin.UpdatedBy = "System";
|
||||
skin.UpdatedAt = DateTime.Now;
|
||||
|
||||
@ -1045,6 +1075,14 @@ public class PetService(
|
||||
if (!result)
|
||||
throw new BusinessException("创建皮肤图片失败", 500);
|
||||
|
||||
// 搬运图片到正式目录
|
||||
if (OssImageHelper.IsTempImage(image.ImageUrl))
|
||||
{
|
||||
var helper = CreateImageHelper();
|
||||
image.ImageUrl = await helper.MoveToFormalAsync(image.ImageUrl, $"pet/skinimage/{image.Id}");
|
||||
await petSkinImageRepository.UpdateAsync(image);
|
||||
}
|
||||
|
||||
logger.LogInformation("创建皮肤图片成功,Id: {Id}, SkinId: {SkinId}", image.Id, image.SkinId);
|
||||
return BuildSkinImageOutput(image);
|
||||
}
|
||||
@ -1063,7 +1101,16 @@ public class PetService(
|
||||
|
||||
image.SkinId = input.SkinId;
|
||||
image.EvolutionStageId = input.EvolutionStageId;
|
||||
image.ImageUrl = input.ImageUrl.Trim();
|
||||
|
||||
// 搬运图片到正式目录
|
||||
var newImageUrl = input.ImageUrl.Trim();
|
||||
if (OssImageHelper.IsTempImage(newImageUrl))
|
||||
{
|
||||
var helper = CreateImageHelper();
|
||||
newImageUrl = await helper.MoveToFormalAsync(newImageUrl, $"pet/skinimage/{image.Id}");
|
||||
}
|
||||
image.ImageUrl = newImageUrl;
|
||||
|
||||
image.SortOrder = input.SortOrder;
|
||||
image.Type = Enum.Parse<PetSkinImageTypeEnum>(input.Type, true);
|
||||
image.UpdatedBy = "System";
|
||||
@ -1123,4 +1170,115 @@ public class PetService(
|
||||
UpdatedAt = i.UpdatedAt
|
||||
};
|
||||
}
|
||||
|
||||
// ==================== 便捷查询接口 ====================
|
||||
|
||||
/// <summary>
|
||||
/// 根据模板Id获取进化链列表(非分页,按StageLevel排序)
|
||||
/// </summary>
|
||||
public async Task<List<PetEvolutionOutput>> GetEvolutionsByTemplateIdAsync(long templateId)
|
||||
{
|
||||
if (templateId <= 0)
|
||||
throw new BusinessException("模板Id不能为空", 400);
|
||||
|
||||
var list = await petEvolutionRepository.Queryable()
|
||||
.Where(e => e.TemplateId == templateId && !e.IsDeleted)
|
||||
.OrderBy(e => e.StageLevel)
|
||||
.ToListAsync();
|
||||
|
||||
return list.Select(BuildEvolutionOutput).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据模板Id获取皮肤列表(非分页,按SortOrder排序)
|
||||
/// </summary>
|
||||
public async Task<List<PetSkinOutput>> GetSkinsByTemplateIdAsync(long templateId)
|
||||
{
|
||||
if (templateId <= 0)
|
||||
throw new BusinessException("模板Id不能为空", 400);
|
||||
|
||||
var list = await petSkinRepository.Queryable()
|
||||
.Where(s => s.TemplateId == templateId && !s.IsDeleted)
|
||||
.OrderBy(s => s.SortOrder)
|
||||
.ToListAsync();
|
||||
|
||||
var result = list.Select(s => new PetSkinOutput
|
||||
{
|
||||
Id = s.Id,
|
||||
TemplateId = s.TemplateId,
|
||||
Name = s.Name,
|
||||
Description = s.Description,
|
||||
Rarity = s.Rarity,
|
||||
SortOrder = s.SortOrder,
|
||||
Type = s.Type.ToString(),
|
||||
CoverImageUrl = s.CoverImageUrl,
|
||||
CreatedBy = s.CreatedBy,
|
||||
CreatedAt = s.CreatedAt,
|
||||
UpdatedBy = s.UpdatedBy,
|
||||
UpdatedAt = s.UpdatedAt
|
||||
}).ToList();
|
||||
|
||||
// 批量查询关联图片
|
||||
var skinIds = result.Select(s => s.Id).ToList();
|
||||
if (skinIds.Count > 0)
|
||||
{
|
||||
var allImages = await petSkinImageRepository.Queryable()
|
||||
.Where(i => skinIds.Contains(i.SkinId) && !i.IsDeleted)
|
||||
.OrderBy(i => i.SortOrder)
|
||||
.ToListAsync();
|
||||
|
||||
var imageMap = allImages
|
||||
.GroupBy(i => i.SkinId)
|
||||
.ToDictionary(g => g.Key, g => g.Select(BuildSkinImageOutput).ToList());
|
||||
|
||||
foreach (var skin in result)
|
||||
{
|
||||
if (imageMap.ContainsKey(skin.Id))
|
||||
skin.Images = imageMap[skin.Id];
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据皮肤Id获取各阶段图片列表(按进化阶段分组,含阶段基本信息)
|
||||
/// </summary>
|
||||
public async Task<List<SkinEvolutionStageOutput>> GetSkinImagesGroupedBySkinIdAsync(long skinId)
|
||||
{
|
||||
if (skinId <= 0)
|
||||
throw new BusinessException("皮肤Id不能为空", 400);
|
||||
|
||||
// 1. 获取皮肤信息
|
||||
var skin = await petSkinRepository.GetByIdAsync(skinId);
|
||||
if (skin == null || skin.IsDeleted)
|
||||
throw new BusinessException("皮肤不存在", 404);
|
||||
|
||||
// 2. 获取该模板的所有进化阶段(按阶段等级排序)
|
||||
var evolutions = await petEvolutionRepository.Queryable()
|
||||
.Where(e => e.TemplateId == skin.TemplateId && !e.IsDeleted)
|
||||
.OrderBy(e => e.StageLevel)
|
||||
.ToListAsync();
|
||||
|
||||
// 3. 获取该皮肤的所有图片
|
||||
var images = await petSkinImageRepository.Queryable()
|
||||
.Where(i => i.SkinId == skinId && !i.IsDeleted)
|
||||
.OrderBy(i => i.SortOrder)
|
||||
.ToListAsync();
|
||||
|
||||
var imagesByStage = images
|
||||
.GroupBy(i => i.EvolutionStageId)
|
||||
.ToDictionary(g => g.Key, g => g.Select(BuildSkinImageOutput).ToList());
|
||||
|
||||
// 4. 组装结果:每个进化阶段 + 对应的图片列表
|
||||
return evolutions.Select(e => new SkinEvolutionStageOutput
|
||||
{
|
||||
EvolutionId = e.Id,
|
||||
StageName = e.StageName,
|
||||
StageLevel = e.StageLevel,
|
||||
RequiredGrowth = e.RequiredGrowth,
|
||||
PreviousEvolutionId = e.PreviousEvolutionId,
|
||||
Images = imagesByStage.GetValueOrDefault(e.Id, new List<PetSkinImageOutput>())
|
||||
}).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user