Files
QYZH.InteractiveMagazine/QYZH.InteractiveMagazine.Service/CheckInConfigService.cs
glz ae4cd627df feat: 完成多模块功能迭代与优化
1.  新增宠物皮肤初始枚举值、下拉列表接口及相关DTO
2.  完善商品实体与DTO,新增虚拟商品标记和类型ID字段
3.  重构用户认证体系,支持多用户切换并重新生成JWT令牌
4.  新增签到配置管理全套功能,包括增删改查和状态管理
5.  优化模型验证过滤器和基础响应类的命名规范
6.  新增补签功能,完善签到服务逻辑
7.  拆分用户详情DTO,新增各子数据分页查询接口
8.  重构微信控制器的用户ID获取逻辑,统一使用激活用户ID
9.  修复背包服务中补签卡的扣减逻辑
10. 新增家长姓名修改接口和相关服务实现
2026-06-10 17:53:38 +08:00

260 lines
8.6 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 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
};
}
}