diff --git a/QYZH.InteractiveMagazine.IService/IPetService.cs b/QYZH.InteractiveMagazine.IService/IPetService.cs
index 8e1563c..15e801c 100644
--- a/QYZH.InteractiveMagazine.IService/IPetService.cs
+++ b/QYZH.InteractiveMagazine.IService/IPetService.cs
@@ -8,7 +8,7 @@ namespace QYZH.InteractiveMagazine.IService;
///
/// 宠物服务接口
///
-public interface IPetService : IBaseService
+public interface IPetService : IBaseService
{
///
/// 获取用户宠物信息
diff --git a/QYZH.InteractiveMagazine.Models/Dto/Pet/PetDto.cs b/QYZH.InteractiveMagazine.Models/Dto/Pet/PetDto.cs
index a935ab0..9f7f6b3 100644
--- a/QYZH.InteractiveMagazine.Models/Dto/Pet/PetDto.cs
+++ b/QYZH.InteractiveMagazine.Models/Dto/Pet/PetDto.cs
@@ -15,6 +15,16 @@ public class PetOutput
///
public long UserId { get; set; }
+ ///
+ /// 宠物模板Id
+ ///
+ public long TemplateId { get; set; }
+
+ ///
+ /// 宠物模板名称
+ ///
+ public string? TemplateName { get; set; }
+
///
/// 宠物昵称
///
diff --git a/QYZH.InteractiveMagazine.Models/Entity/PetEvolution.cs b/QYZH.InteractiveMagazine.Models/Entity/PetEvolution.cs
index 3873010..b243f7c 100644
--- a/QYZH.InteractiveMagazine.Models/Entity/PetEvolution.cs
+++ b/QYZH.InteractiveMagazine.Models/Entity/PetEvolution.cs
@@ -10,6 +10,13 @@ namespace QYZH.InteractiveMagazine.Models.Entity
{
public PetEvolution() { }
+ ///
+ /// Desc:所属宠物模板Id(关联PetTemplate.Id)
+ /// Default:
+ /// Nullable:False
+ ///
+ public long TemplateId { get; set; }
+
///
/// Desc:阶段名称
/// Default:
diff --git a/QYZH.InteractiveMagazine.Models/Entity/PetSkin.cs b/QYZH.InteractiveMagazine.Models/Entity/PetSkin.cs
index bcbea9a..07c8f32 100644
--- a/QYZH.InteractiveMagazine.Models/Entity/PetSkin.cs
+++ b/QYZH.InteractiveMagazine.Models/Entity/PetSkin.cs
@@ -10,6 +10,13 @@ namespace QYZH.InteractiveMagazine.Models.Entity
{
public PetSkin() { }
+ ///
+ /// Desc:所属宠物模板Id(关联PetTemplate.Id)
+ /// Default:
+ /// Nullable:False
+ ///
+ public long TemplateId { get; set; }
+
///
/// Desc:皮肤名称
/// Default:
diff --git a/QYZH.InteractiveMagazine.Models/Entity/PetTemplate.cs b/QYZH.InteractiveMagazine.Models/Entity/PetTemplate.cs
new file mode 100644
index 0000000..1453f4b
--- /dev/null
+++ b/QYZH.InteractiveMagazine.Models/Entity/PetTemplate.cs
@@ -0,0 +1,62 @@
+using SqlSugar;
+
+namespace QYZH.InteractiveMagazine.Models.Entity
+{
+ ///
+ /// 宠物模板表(定义不同宠物种类,支持后期多宠物扩展)
+ ///
+ [SugarTable("PetTemplate")]
+ public partial class PetTemplate : SqlSugarBaseEntity
+ {
+ public PetTemplate() { }
+
+ ///
+ /// Desc:模板名称
+ /// Default:
+ /// Nullable:False
+ ///
+ public string Name { get; set; }
+
+ ///
+ /// Desc:模板描述
+ /// Default:
+ /// Nullable:True
+ ///
+ public string Description { get; set; }
+
+ ///
+ /// Desc:默认初始进化形态Id(关联PetEvolution.Id)
+ /// Default:
+ /// Nullable:False
+ ///
+ public long DefaultEvolutionId { get; set; }
+
+ ///
+ /// Desc:模板图标地址
+ /// Default:
+ /// Nullable:True
+ ///
+ public string IconUrl { get; set; }
+
+ ///
+ /// Desc:排序权重
+ /// Default:0
+ /// Nullable:False
+ ///
+ public int SortOrder { get; set; }
+
+ ///
+ /// Desc:模板类型: Normal, Special, Limited
+ /// Default:Normal
+ /// Nullable:False
+ ///
+ public string Type { get; set; }
+
+ ///
+ /// Desc:状态: Active, Inactive
+ /// Default:Active
+ /// Nullable:False
+ ///
+ public new string Status { get; set; }
+ }
+}
diff --git a/QYZH.InteractiveMagazine.Models/Entity/Pet.cs b/QYZH.InteractiveMagazine.Models/Entity/UserPet.cs
similarity index 85%
rename from QYZH.InteractiveMagazine.Models/Entity/Pet.cs
rename to QYZH.InteractiveMagazine.Models/Entity/UserPet.cs
index 8beb35c..4bf4d26 100644
--- a/QYZH.InteractiveMagazine.Models/Entity/Pet.cs
+++ b/QYZH.InteractiveMagazine.Models/Entity/UserPet.cs
@@ -3,12 +3,12 @@ using SqlSugar;
namespace QYZH.InteractiveMagazine.Models.Entity
{
///
- ///宠物实例表
+ ///用户宠物实例表
///
- [SugarTable("Pet")]
- public partial class Pet : SqlSugarBaseEntity
+ [SugarTable("UserPet")]
+ public partial class UserPet : SqlSugarBaseEntity
{
- public Pet()
+ public UserPet()
{
@@ -20,6 +20,13 @@ namespace QYZH.InteractiveMagazine.Models.Entity
///
public long UserId { get; set; }
+ ///
+ /// Desc:宠物模板Id(关联PetTemplate.Id)
+ /// Default:
+ /// Nullable:False
+ ///
+ public long TemplateId { get; set; }
+
///
/// Desc:宠物昵称
/// Default:
diff --git a/QYZH.InteractiveMagazine.Service/CheckInService.cs b/QYZH.InteractiveMagazine.Service/CheckInService.cs
index df0913c..a084782 100644
--- a/QYZH.InteractiveMagazine.Service/CheckInService.cs
+++ b/QYZH.InteractiveMagazine.Service/CheckInService.cs
@@ -60,7 +60,7 @@ public class CheckInService(
}
// 5. 查询用户宠物(如果有)
- var pet = await checkInRecordRepository.Context.Queryable()
+ var pet = await checkInRecordRepository.Context.Queryable()
.Where(p => p.UserId == userId && !p.IsDeleted)
.FirstAsync();
@@ -258,7 +258,7 @@ public class CheckInService(
throw new BusinessException("用户不存在", 404);
// 查询宠物
- var pet = await checkInRecordRepository.Context.Queryable()
+ var pet = await checkInRecordRepository.Context.Queryable()
.Where(p => p.UserId == userId && !p.IsDeleted)
.FirstAsync();
diff --git a/QYZH.InteractiveMagazine.Service/PetService.cs b/QYZH.InteractiveMagazine.Service/PetService.cs
index 0e3d1bc..b45c6d0 100644
--- a/QYZH.InteractiveMagazine.Service/PetService.cs
+++ b/QYZH.InteractiveMagazine.Service/PetService.cs
@@ -13,13 +13,14 @@ namespace QYZH.InteractiveMagazine.Service;
/// 宠物服务实现
///
public class PetService(
- BaseRepository petRepository,
+ BaseRepository petRepository,
+ BaseRepository petTemplateRepository,
BaseRepository feedingRecordRepository,
BaseRepository petEvolutionRepository,
BaseRepository petSkinImageRepository,
BaseRepository petSkinRepository,
ILogger logger)
- : BaseRepository, IPetService
+ : BaseRepository, IPetService
{
///
/// 获取用户宠物信息(含当前形态名称、皮肤图片序列)
@@ -39,6 +40,11 @@ public class PetService(
.Where(e => e.Id == pet.CurrentEvolutionId)
.FirstAsync();
+ // 查询宠物模板名称
+ var template = await petTemplateRepository.Queryable()
+ .Where(t => t.Id == pet.TemplateId && !t.IsDeleted)
+ .FirstAsync();
+
// 查询当前皮肤名称
string? skinName = null;
if (pet.CurrentSkinId > 0)
@@ -68,6 +74,8 @@ public class PetService(
{
Id = pet.Id,
UserId = pet.UserId,
+ TemplateId = pet.TemplateId,
+ TemplateName = template?.Name,
Name = pet.Name,
CurrentEvolutionId = pet.CurrentEvolutionId,
EvolutionStageName = evolution?.StageName,
@@ -90,7 +98,7 @@ public class PetService(
logger.LogInformation("为用户创建默认宠物,UserId: {UserId}", userId);
// 检查用户是否已有宠物
- var exists = petRepository.Context.Queryable()
+ var exists = petRepository.Context.Queryable()
.Any(p => p.UserId == userId);
if (exists)
{
@@ -98,16 +106,31 @@ public class PetService(
return;
}
- // 查询初始进化形态(PreviousEvolutionId 为 null 的即为初始形态)
+ // 查询默认宠物模板(取排序权重最低且状态为Active的模板)
+ var defaultTemplate = await petTemplateRepository.Queryable()
+ .Where(t => t.Status == "Active" && !t.IsDeleted)
+ .OrderBy(t => t.SortOrder)
+ .FirstAsync();
+
+ if (defaultTemplate == null)
+ {
+ logger.LogError("未找到可用的宠物模板");
+ throw new Exception("宠物模板配置缺失");
+ }
+
+ // 查询模板对应的初始进化形态
var initialEvolution = await petEvolutionRepository.Queryable()
- .Where(e => e.PreviousEvolutionId == null && e.Status == "Active")
+ .Where(e => e.TemplateId == defaultTemplate.Id
+ && e.PreviousEvolutionId == null
+ && e.Status == "Active")
.OrderBy(e => e.StageLevel)
.FirstAsync();
- var pet = new Pet
+ var pet = new UserPet
{
UserId = userId,
- Name = "小精灵",
+ TemplateId = defaultTemplate.Id,
+ Name = defaultTemplate.Name,
CurrentEvolutionId = initialEvolution?.Id ?? 0,
GrowthPoints = 0,
FeedingCount = 0,
@@ -156,7 +179,7 @@ public class PetService(
}
var result = await petRepository.UpdateAsync(
- p => new Pet { Status = "Active" },
+ p => new UserPet { Status = "Active" },
p => p.UserId == userId);
if (!result)
@@ -217,7 +240,7 @@ public class PetService(
await UseTranAsync(async () =>
{
// 累加成长值和喂养次数
- var updateResult = await petRepository.Context.Updateable()
+ var updateResult = await petRepository.Context.Updateable()
.SetColumns(p => p.GrowthPoints == growthAfter)
.SetColumns(p => p.FeedingCount == p.FeedingCount + 1)
.SetColumns(p => p.UpdatedAt == DateTime.Now)
@@ -241,7 +264,7 @@ public class PetService(
if (nextEvolution != null)
{
// 触发进化
- var evolveResult = await petRepository.Context.Updateable()
+ var evolveResult = await petRepository.Context.Updateable()
.SetColumns(p => p.CurrentEvolutionId == nextEvolution.Id)
.SetColumns(p => p.UpdatedAt == DateTime.Now)
.SetColumns(p => p.UpdatedBy == userId.ToString())
diff --git a/QYZH.InteractiveMagazine.Service/WxMallService.cs b/QYZH.InteractiveMagazine.Service/WxMallService.cs
index e7db82c..bce4cf8 100644
--- a/QYZH.InteractiveMagazine.Service/WxMallService.cs
+++ b/QYZH.InteractiveMagazine.Service/WxMallService.cs
@@ -495,7 +495,7 @@ public class WxMallService(
logger.LogInformation("宠物换肤,UserId: {UserId}, SkinId: {SkinId}", userId, input.SkinId);
// 查询用户宠物
- var pet = await exchangeRecordRepository.Context.Queryable()
+ var pet = await exchangeRecordRepository.Context.Queryable()
.Where(p => p.UserId == userId && !p.IsDeleted)
.FirstAsync();
@@ -505,7 +505,7 @@ public class WxMallService(
if (input.SkinId == 0)
{
// 恢复默认皮肤
- await exchangeRecordRepository.Context.Updateable()
+ await exchangeRecordRepository.Context.Updateable()
.SetColumns(p => p.CurrentSkinId == 0)
.SetColumns(p => p.UpdatedAt == DateTime.Now)
.Where(p => p.Id == pet.Id)
@@ -535,7 +535,7 @@ public class WxMallService(
throw new BusinessException("您尚未拥有该皮肤,请先兑换", 400);
// 换肤
- await exchangeRecordRepository.Context.Updateable()
+ await exchangeRecordRepository.Context.Updateable()
.SetColumns(p => p.CurrentSkinId == skin.Id)
.SetColumns(p => p.UpdatedAt == DateTime.Now)
.Where(p => p.Id == pet.Id)