1. 新增宠物皮肤初始枚举值、下拉列表接口及相关DTO 2. 完善商品实体与DTO,新增虚拟商品标记和类型ID字段 3. 重构用户认证体系,支持多用户切换并重新生成JWT令牌 4. 新增签到配置管理全套功能,包括增删改查和状态管理 5. 优化模型验证过滤器和基础响应类的命名规范 6. 新增补签功能,完善签到服务逻辑 7. 拆分用户详情DTO,新增各子数据分页查询接口 8. 重构微信控制器的用户ID获取逻辑,统一使用激活用户ID 9. 修复背包服务中补签卡的扣减逻辑 10. 新增家长姓名修改接口和相关服务实现
260 lines
8.6 KiB
C#
260 lines
8.6 KiB
C#
using Microsoft.Extensions.Logging;
|
||
using QYZH.InteractiveMagazine.IService;
|
||
using QYZH.InteractiveMagazine.Models.Common;
|
||
using QYZH.InteractiveMagazine.Models.Dto;
|
||
using QYZH.InteractiveMagazine.Models.Dto.CheckIn;
|
||
using QYZH.InteractiveMagazine.Models.Entity;
|
||
using QYZH.InteractiveMagazine.Models.Enum;
|
||
using QYZH.InteractiveMagazine.Repository;
|
||
using SqlSugar;
|
||
|
||
namespace QYZH.InteractiveMagazine.Service;
|
||
|
||
/// <summary>
|
||
/// 签到配置服务实现
|
||
/// </summary>
|
||
public class CheckInConfigService(
|
||
BaseRepository<CheckInConfig> checkInConfigRepository,
|
||
ILogger<CheckInConfigService> logger)
|
||
: BaseRepository<CheckInConfig>, ICheckInConfigService
|
||
{
|
||
/// <summary>
|
||
/// 创建签到配置
|
||
/// </summary>
|
||
public async Task<CheckInConfigOutput> CreateAsync(CheckInConfigInput input)
|
||
{
|
||
logger.LogInformation("正在创建签到配置,DayNumber: {DayNumber}, Type: {Type}", input.DayNumber, input.Type);
|
||
|
||
if (input.DayNumber <= 0)
|
||
{
|
||
throw new BusinessException("连续签到天数必须大于0", 400);
|
||
}
|
||
|
||
if (input.RewardPoints < 0)
|
||
{
|
||
throw new BusinessException("奖励积分不能为负数", 400);
|
||
}
|
||
|
||
if (input.BonusPoints < 0)
|
||
{
|
||
throw new BusinessException("额外奖励积分不能为负数", 400);
|
||
}
|
||
|
||
// 检查同类型下是否已存在相同天数配置
|
||
var exists = await checkInConfigRepository.Context.Queryable<CheckInConfig>()
|
||
.Where(c => c.Type == input.Type && c.DayNumber == input.DayNumber && !c.IsDeleted)
|
||
.AnyAsync();
|
||
|
||
if (exists)
|
||
{
|
||
throw new BusinessException($"该类型下已存在连续{input.DayNumber}天的配置", 400);
|
||
}
|
||
|
||
var config = new CheckInConfig
|
||
{
|
||
DayNumber = input.DayNumber,
|
||
RewardPoints = input.RewardPoints,
|
||
BonusPoints = input.BonusPoints,
|
||
Type = input.Type,
|
||
Status = (int)DefaultStatusEnum.Active,
|
||
CreatedBy = "System",
|
||
UpdatedBy = "System",
|
||
CreatedAt = DateTime.Now,
|
||
UpdatedAt = DateTime.Now,
|
||
IsDeleted = false
|
||
};
|
||
|
||
var result = await checkInConfigRepository.InsertAsync(config);
|
||
if (!result)
|
||
{
|
||
throw new BusinessException("创建签到配置失败", 500);
|
||
}
|
||
|
||
logger.LogInformation("签到配置创建成功,ID: {Id}", config.Id);
|
||
return MapToOutput(config);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新签到配置
|
||
/// </summary>
|
||
public async Task<CheckInConfigOutput> UpdateAsync(long id, CheckInConfigInput input)
|
||
{
|
||
logger.LogInformation("正在更新签到配置,ID: {Id}", id);
|
||
|
||
var config = await checkInConfigRepository.GetByIdAsync(id);
|
||
if (config == null)
|
||
{
|
||
logger.LogWarning("未找到要更新的签到配置,ID: {Id}", id);
|
||
throw new BusinessException("签到配置不存在", 404);
|
||
}
|
||
|
||
if (input.DayNumber <= 0)
|
||
{
|
||
throw new BusinessException("连续签到天数必须大于0", 400);
|
||
}
|
||
|
||
if (input.RewardPoints < 0)
|
||
{
|
||
throw new BusinessException("奖励积分不能为负数", 400);
|
||
}
|
||
|
||
if (input.BonusPoints < 0)
|
||
{
|
||
throw new BusinessException("额外奖励积分不能为负数", 400);
|
||
}
|
||
|
||
// 检查同类型下是否已存在相同天数配置(排除自身)
|
||
var exists = await checkInConfigRepository.Context.Queryable<CheckInConfig>()
|
||
.Where(c => c.Type == input.Type && c.DayNumber == input.DayNumber && c.Id != id && !c.IsDeleted)
|
||
.AnyAsync();
|
||
|
||
if (exists)
|
||
{
|
||
throw new BusinessException($"该类型下已存在连续{input.DayNumber}天的配置", 400);
|
||
}
|
||
|
||
config.DayNumber = input.DayNumber;
|
||
config.RewardPoints = input.RewardPoints;
|
||
config.BonusPoints = input.BonusPoints;
|
||
config.Type = input.Type;
|
||
config.UpdatedBy = "System";
|
||
config.UpdatedAt = DateTime.Now;
|
||
|
||
var updateResult = await checkInConfigRepository.UpdateAsync(config);
|
||
if (!updateResult)
|
||
{
|
||
throw new BusinessException("更新签到配置失败", 500);
|
||
}
|
||
|
||
logger.LogInformation("签到配置更新成功,ID: {Id}", id);
|
||
return MapToOutput(config);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 删除签到配置(软删除)
|
||
/// </summary>
|
||
public async Task DeleteAsync(long id)
|
||
{
|
||
logger.LogInformation("正在删除签到配置,ID: {Id}", id);
|
||
|
||
var config = await checkInConfigRepository.GetByIdAsync(id);
|
||
if (config == null)
|
||
{
|
||
logger.LogWarning("未找到要删除的签到配置,ID: {Id}", id);
|
||
throw new BusinessException("签到配置不存在", 404);
|
||
}
|
||
|
||
var result = await checkInConfigRepository.Context.Updateable<CheckInConfig>()
|
||
.SetColumns(c => new CheckInConfig
|
||
{
|
||
IsDeleted = true,
|
||
UpdatedBy = "System",
|
||
UpdatedAt = DateTime.Now
|
||
})
|
||
.Where(c => c.Id == id)
|
||
.ExecuteCommandAsync();
|
||
|
||
if (result <= 0)
|
||
{
|
||
throw new BusinessException("删除签到配置失败", 500);
|
||
}
|
||
|
||
logger.LogInformation("签到配置删除成功,ID: {Id}", id);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 根据ID获取签到配置
|
||
/// </summary>
|
||
public async Task<CheckInConfigOutput> GetByIdAsync(long id)
|
||
{
|
||
var config = await checkInConfigRepository.GetByIdAsync(id);
|
||
if (config == null)
|
||
{
|
||
throw new BusinessException("签到配置不存在", 404);
|
||
}
|
||
|
||
return MapToOutput(config);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 分页查询签到配置列表
|
||
/// </summary>
|
||
public async Task<PageListModel<CheckInConfigOutput>> GetListAsync(CheckInConfigQueryInput input)
|
||
{
|
||
logger.LogInformation("正在查询签到配置列表,页码: {PageIndex}, 每页条数: {PageSize}", input.PageIndex, input.PageSize);
|
||
|
||
if (input.PageIndex <= 0)
|
||
{
|
||
throw new BusinessException("页码必须大于0", 400);
|
||
}
|
||
|
||
if (input.PageSize <= 0 || input.PageSize > 100)
|
||
{
|
||
throw new BusinessException("每页条数必须在1-100之间", 400);
|
||
}
|
||
|
||
RefAsync<int> totalNumber = 0;
|
||
var configs = await checkInConfigRepository.Queryable()
|
||
.Where(c => !c.IsDeleted)
|
||
.WhereIF(input.Type.HasValue, c => c.Type == input.Type.Value)
|
||
.OrderBy(c => c.Type)
|
||
.OrderBy(c => c.DayNumber)
|
||
.ToPageListAsync(input.PageIndex, input.PageSize, totalNumber);
|
||
|
||
var pageResult = configs.Select(MapToOutput).ToList();
|
||
|
||
var result = new PageListModel<CheckInConfigOutput>(new List<CheckInConfigOutput>(), input.PageIndex, input.PageSize, totalNumber);
|
||
result.Result = pageResult;
|
||
return result;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新签到配置启用/禁用状态
|
||
/// </summary>
|
||
public async Task<bool> UpdateStatusAsync(long id)
|
||
{
|
||
var config = await checkInConfigRepository.GetByIdAsync(id);
|
||
if (config == null)
|
||
{
|
||
logger.LogWarning("未找到要更新状态的签到配置,ID: {Id}", id);
|
||
throw new BusinessException("签到配置不存在", 404);
|
||
}
|
||
|
||
config.Status = config.Status == (int)DefaultStatusEnum.Active
|
||
? (int)DefaultStatusEnum.Inactive
|
||
: (int)DefaultStatusEnum.Active;
|
||
config.UpdatedBy = "System";
|
||
config.UpdatedAt = DateTime.Now;
|
||
|
||
var result = await checkInConfigRepository.UpdateAsync(config);
|
||
if (!result)
|
||
{
|
||
logger.LogError("签到配置状态更新失败,ID: {Id}", id);
|
||
throw new BusinessException("更新签到配置状态失败", 500);
|
||
}
|
||
|
||
logger.LogInformation("签到配置状态更新成功,ID: {Id}, Status: {Status}", id, config.Status);
|
||
return result;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 实体映射为输出DTO
|
||
/// </summary>
|
||
private static CheckInConfigOutput MapToOutput(CheckInConfig config)
|
||
{
|
||
return new CheckInConfigOutput
|
||
{
|
||
Id = config.Id,
|
||
DayNumber = config.DayNumber,
|
||
RewardPoints = config.RewardPoints,
|
||
BonusPoints = config.BonusPoints,
|
||
Type = config.Type,
|
||
Status = config.Status,
|
||
CreatedBy = config.CreatedBy,
|
||
CreatedAt = config.CreatedAt,
|
||
UpdatedBy = config.UpdatedBy,
|
||
UpdatedAt = config.UpdatedAt
|
||
};
|
||
}
|
||
}
|