refactor: 批量新增枚举类型并完成实体、DTO、服务层枚举替换

- 新增30+业务枚举类型覆盖用户、宠物、商城、社区、积分等模块
- 完成实体类、DTO、服务层的字符串枚举替换为强类型枚举
- 修复用户状态枚举名称变更,将Frozen改为Disabled
- 新增批量发布社区消息接口与控制器实现
- 新增操作日志、积分管理、补偿任务相关服务与DTO
This commit is contained in:
glz
2026-06-08 16:57:44 +08:00
parent 698c404b72
commit 78b686f9e5
116 changed files with 4861 additions and 307 deletions

View File

@ -0,0 +1,145 @@
using Microsoft.Extensions.Logging;
using QYZH.InteractiveMagazine.IService;
using QYZH.InteractiveMagazine.Models.Common;
using QYZH.InteractiveMagazine.Models.Dto;
using QYZH.InteractiveMagazine.Models.Entity;
using QYZH.InteractiveMagazine.Repository;
using Serilog.Core;
using SqlSugar;
namespace QYZH.InteractiveMagazine.Service;
/// <summary>
/// 操作日志服务实现
/// </summary>
public class OperationLogService(
BaseRepository<OperationLog> operationLogRepository,
BaseRepository<AdminUser> adminUserRepository,
BaseRepository<Users> usersRepository,
ILogger<OperationLogService> logger) : BaseRepository<OperationLog>, IOperationLogService
{
/// <summary>
/// 记录操作日志
/// </summary>
public async Task LogAsync(long operatorId, string operatorName, string actionType, string targetType, long targetId, string? targetName = null, string? detail = null, string? ipAddress = null)
{
try
{
var log = new OperationLog
{
OperatorId = operatorId,
OperatorName = operatorName,
ActionType = actionType,
TargetType = targetType,
TargetId = targetId,
TargetName = targetName,
Detail = detail,
IpAddress = ipAddress,
IsDeleted = false,
CreatedBy = operatorName,
CreatedAt = DateTime.Now,
UpdatedBy = operatorName,
UpdatedAt = DateTime.Now
};
await operationLogRepository.InsertAsync(log);
logger.LogInformation(
"记录操作日志Operator: {Operator}, Action: {Action}, Target: {TargetType}/{TargetId}",
operatorName, actionType, targetType, targetId);
}
catch (Exception ex)
{
// 日志记录不应影响主业务流程
logger.LogError(ex, "记录操作日志失败Operator: {Operator}, Action: {Action}", operatorName, actionType);
}
}
/// <summary>
/// 分页查询操作日志
/// </summary>
public async Task<PageListModel<OperationLogOutput>> GetListAsync(OperationLogQueryInput input)
{
if (input.PageIndex <= 0)
input.PageIndex = 1;
if (input.PageSize <= 0 || input.PageSize > 100)
input.PageSize = 10;
RefAsync<int> totalNumber = 0;
var pageResult = await operationLogRepository.Queryable()
.WhereIF(!string.IsNullOrWhiteSpace(input.OperatorName), l => l.OperatorName.Contains(input.OperatorName))
.WhereIF(!string.IsNullOrWhiteSpace(input.ActionType), l => l.ActionType == input.ActionType)
.WhereIF(!string.IsNullOrWhiteSpace(input.TargetType), l => l.TargetType == input.TargetType)
.WhereIF(input.TargetId.HasValue, l => l.TargetId == input.TargetId.Value)
.OrderByDescending(l => l.CreatedAt)
.Select(l => new OperationLogOutput
{
Id = l.Id,
OperatorId = l.OperatorId,
OperatorName = l.OperatorName,
ActionType = l.ActionType,
TargetType = l.TargetType,
TargetId = l.TargetId,
TargetName = l.TargetName,
Detail = l.Detail,
IpAddress = l.IpAddress,
CreatedAt = l.CreatedAt
})
.ToPageListAsync(input.PageIndex, input.PageSize, totalNumber);
return new PageListModel<OperationLogOutput>(pageResult, input.PageIndex, input.PageSize, totalNumber);
}
/// <summary>
/// 获取操作日志详情
/// </summary>
public async Task<OperationLogDetailOutput> GetDetailAsync(long id)
{
var log = await operationLogRepository.Queryable()
.Where(l => l.Id == id && !l.IsDeleted)
.FirstAsync();
if (log == null)
{
throw new BusinessException("操作日志记录不存在");
}
var result = new OperationLogDetailOutput
{
Id = log.Id,
ActionType = log.ActionType,
TargetType = log.TargetType,
TargetId = log.TargetId,
TargetName = log.TargetName,
Detail = log.Detail,
IpAddress = log.IpAddress,
CreatedAt = log.CreatedAt,
OperatorName = log.OperatorName
};
// 查询操作人详细信息
var adminUser = await adminUserRepository.GetByIdAsync(log.OperatorId);
if (adminUser != null)
{
result.OperatorRole = adminUser.Type.ToString();
}
// 当目标类型为用户时,查询被操作人信息
if (log.TargetType == OperationLogTargetType.User)
{
var targetUser = await usersRepository.GetByIdAsync(log.TargetId);
if (targetUser != null)
{
result.TargetUserName = targetUser.Name;
result.TargetUserPhone = targetUser.Phone;
result.TargetUserAvatar = targetUser.AvatarUrl;
}
}
return result;
}
}