refactor: 重构状态更新接口,新增商品管理与勋章规则配置

1. 重构用户、宠物模板、勋章、管理员状态更新接口,移除冗余参数改为自动切换状态
2. 重命名宠物背景枚举为宠物皮肤,调整商品状态字段为枚举类型
3. 新增商品上下架状态管理接口与对应逻辑
4. 新增勋章规则配置系统,支持动态加载可用表和字段
5. 优化商品查询与展示逻辑,适配新的状态字段
This commit is contained in:
glz
2026-06-09 11:41:28 +08:00
parent 0126c6b097
commit 1d86580db7
24 changed files with 405 additions and 61 deletions

View File

@ -203,4 +203,32 @@ public class AdminUserService(BaseRepository<AdminUser> adminUserRepository, ILo
.ToPageListAsync(input.PageIndex, input.PageSize, totalNumber);
return new PageListModel<AdminUserOutput>(pageResult, input.PageIndex, input.PageSize, totalNumber);
}
/// <summary>
/// 切换管理员状态(激活/冻结)
/// </summary>
public async Task ToggleStatusAsync(long id)
{
logger.LogInformation("正在切换管理员状态ID: {Id}", id);
var adminUser = await adminUserRepository.GetByIdAsync(id);
if (adminUser == null)
{
logger.LogWarning("未找到要更新状态的管理员ID: {Id}", id);
throw new BusinessException("管理员不存在", 404);
}
adminUser.Status = adminUser.Status==(int)AdminUserStatusEnum.Active?(int)AdminUserStatusEnum.Inactive:(int)AdminUserStatusEnum.Active;
adminUser.UpdatedBy = "System";
adminUser.UpdatedAt = DateTime.Now;
var result = await adminUserRepository.UpdateAsync(adminUser);
if (!result)
{
logger.LogError("管理员状态更新失败ID: {Id}", id);
throw new BusinessException("更新管理员状态失败", 500);
}
logger.LogInformation("管理员状态更新成功ID: {Id}", id);
}
}

View File

@ -1,10 +1,12 @@
using System.Text.Json;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using QYZH.InteractiveMagazine.IService;
using QYZH.InteractiveMagazine.Models.Common;
using QYZH.InteractiveMagazine.Models.Dto;
using QYZH.InteractiveMagazine.Models.Entity;
using QYZH.InteractiveMagazine.Models.Enum;
using QYZH.InteractiveMagazine.Models.Settings;
using QYZH.InteractiveMagazine.Repository;
using SqlSugar;
@ -13,7 +15,7 @@ namespace QYZH.InteractiveMagazine.Service;
/// <summary>
/// 勋章服务实现
/// </summary>
public class MedalService(BaseRepository<Medal> medalRepository, ILogger<MedalService> logger) : BaseRepository<Medal>, IMedalService
public class MedalService(BaseRepository<Medal> medalRepository, IOptions<MedalRuleConfigSettings> medalRuleConfig, ILogger<MedalService> logger) : BaseRepository<Medal>, IMedalService
{
/// <summary>
@ -257,15 +259,8 @@ public class MedalService(BaseRepository<Medal> medalRepository, ILogger<MedalSe
/// <summary>
/// 更新勋章启用/禁用状态
/// </summary>
public async Task UpdateStatusAsync(long id, int status)
public async Task<bool> UpdateStatusAsync(long id)
{
logger.LogInformation("正在更新勋章状态ID: {Id}, Status: {Status}", id, status);
if (status != 0 && status != 1)
{
throw new BusinessException("状态值无效只能为0(禁用)或1(启用)", 400);
}
var medal = await medalRepository.GetByIdAsync(id);
if (medal == null)
{
@ -273,7 +268,7 @@ public class MedalService(BaseRepository<Medal> medalRepository, ILogger<MedalSe
throw new BusinessException("勋章不存在", 404);
}
medal.Status = status;
medal.Status = medal.Status == 0 ? 1 : 0;
medal.UpdatedBy = "System";
medal.UpdatedAt = DateTime.Now;
@ -283,8 +278,9 @@ public class MedalService(BaseRepository<Medal> medalRepository, ILogger<MedalSe
logger.LogError("勋章状态更新失败ID: {Id}", id);
throw new BusinessException("更新勋章状态失败", 500);
}
logger.LogInformation("勋章状态更新成功ID: {Id}, Status: {Status}", id, status);
logger.LogInformation("勋章状态更新成功ID: {Id}, Status: {Status}", id, medal.Status);
return result;
}
/// <summary>
@ -423,6 +419,40 @@ public class MedalService(BaseRepository<Medal> medalRepository, ILogger<MedalSe
logger.LogInformation("勋章激活成功用户ID: {UserId}, 勋章ID: {MedalId}", userId, input.MedalId);
}
/// <summary>
/// 获取规则配置中可用的目标表列表
/// </summary>
public Task<List<MedalRuleTableOptionOutput>> GetAvailableTablesAsync()
{
var tables = medalRuleConfig.Value.Tables?.Select(t => new MedalRuleTableOptionOutput
{
TableName = t.TableName,
DisplayName = t.DisplayName
}).ToList() ?? new List<MedalRuleTableOptionOutput>();
return Task.FromResult(tables);
}
/// <summary>
/// 获取指定表的可用字段列表
/// </summary>
public Task<List<MedalRuleFieldOptionOutput>> GetTableFieldsAsync(string tableName)
{
var table = medalRuleConfig.Value.Tables?.FirstOrDefault(t => t.TableName == tableName);
if (table == null)
{
return Task.FromResult(new List<MedalRuleFieldOptionOutput>());
}
var fields = table.Fields.Select(f => new MedalRuleFieldOptionOutput
{
FieldName = f.FieldName,
DisplayName = f.DisplayName
}).ToList();
return Task.FromResult(fields);
}
#region
/// <summary>

View File

@ -484,18 +484,20 @@ public class PetService(
/// <summary>
/// 更新模板状态(启用/禁用)
/// </summary>
public async Task UpdateTemplateStatusAsync(long id, int status)
public async Task UpdateTemplateStatusAsync(long id)
{
var template = await petTemplateRepository.GetByIdAsync(id);
if (template == null || template.IsDeleted)
throw new BusinessException("宠物模板不存在", 404);
template.Status = status;
template.Status = template.Status == (int)PetTemplateStatusEnum.Active
? (int)PetTemplateStatusEnum.Inactive
: (int)PetTemplateStatusEnum.Active;
template.UpdatedBy = "System";
template.UpdatedAt = DateTime.Now;
await petTemplateRepository.UpdateAsync(template);
logger.LogInformation("更新模板状态成功Id: {Id}, Status: {Status}", id, status);
logger.LogInformation("更新模板状态成功Id: {Id}, Status: {Status}", id, template.Status);
}
private static PetTemplateOutput BuildTemplateOutput(PetTemplate t)

View File

@ -44,7 +44,7 @@ public class ProductService(BaseRepository<Product> productRepository, ILogger<P
ImageUrl = input.ImageUrl,
Price = input.Price,
Type = Enum.Parse<ProductTypeEnum>(input.Type, true),
SaleStatus = input.SaleStatus,
Status = (int)input.Status,
MetaData = input.MetaData,
IsActive = input.IsActive,
Stock = input.Stock,
@ -72,7 +72,7 @@ public class ProductService(BaseRepository<Product> productRepository, ILogger<P
ImageUrl = product.ImageUrl,
Price = product.Price,
Type = product.Type.ToString(),
SaleStatus = product.SaleStatus,
Status = product.Status.ToString(),
MetaData = product.MetaData,
IsActive = product.IsActive,
Stock = product.Stock,
@ -117,7 +117,7 @@ public class ProductService(BaseRepository<Product> productRepository, ILogger<P
product.ImageUrl = input.ImageUrl;
product.Price = input.Price;
product.Type = Enum.Parse<ProductTypeEnum>(input.Type, true);
product.SaleStatus = input.SaleStatus;
product.Status = (int)input.Status;
product.MetaData = input.MetaData;
product.IsActive = input.IsActive;
product.Stock = input.Stock;
@ -141,7 +141,7 @@ public class ProductService(BaseRepository<Product> productRepository, ILogger<P
ImageUrl = product.ImageUrl,
Price = product.Price,
Type = product.Type.ToString(),
SaleStatus = product.SaleStatus,
Status = product.Status.ToString(),
MetaData = product.MetaData,
IsActive = product.IsActive,
Stock = product.Stock,
@ -198,7 +198,7 @@ public class ProductService(BaseRepository<Product> productRepository, ILogger<P
ImageUrl = product.ImageUrl,
Price = product.Price,
Type = product.Type.ToString(),
SaleStatus = product.SaleStatus,
Status = product.Status.ToString(),
MetaData = product.MetaData,
IsActive = product.IsActive,
Stock = product.Stock,
@ -230,7 +230,7 @@ public class ProductService(BaseRepository<Product> productRepository, ILogger<P
var pageResult = await productRepository.Queryable()
.WhereIF(!string.IsNullOrWhiteSpace(input.Name), p => p.Name.Contains(input.Name))
.WhereIF(!string.IsNullOrWhiteSpace(input.Type), p => p.Type.ToString() == input.Type)
.WhereIF(!string.IsNullOrWhiteSpace(input.SaleStatus), p => p.SaleStatus == input.SaleStatus)
.WhereIF(input.Status.HasValue, p => p.Status == (int)input.Status)
.WhereIF(input.IsActive.HasValue, p => p.IsActive == input.IsActive.Value)
.OrderByDescending(p => p.CreatedAt)
.Select(p => new ProductOutput
@ -241,7 +241,7 @@ public class ProductService(BaseRepository<Product> productRepository, ILogger<P
ImageUrl = p.ImageUrl,
Price = p.Price,
Type = p.Type.ToString(),
SaleStatus = p.SaleStatus,
Status = p.Status.ToString(),
MetaData = p.MetaData,
IsActive = p.IsActive,
Stock = p.Stock,
@ -254,4 +254,34 @@ public class ProductService(BaseRepository<Product> productRepository, ILogger<P
return new PageListModel<ProductOutput>(pageResult, input.PageIndex, input.PageSize, totalNumber);
}
/// <summary>
/// 更新商品上架/下架状态(取反)
/// </summary>
public async Task UpdateSaleStatusAsync(long id)
{
logger.LogInformation("正在更新商品上下架状态ID: {Id}", id);
var product = await productRepository.GetByIdAsync(id);
if (product == null)
{
logger.LogWarning("未找到要更新状态的商品ID: {Id}", id);
throw new BusinessException("商品不存在", 404);
}
product.Status = product.Status == (int)ProductStatusEnum.OnSale
? (int)ProductStatusEnum.OffSale
: (int)ProductStatusEnum.OnSale;
product.UpdatedBy = "System";
product.UpdatedAt = DateTime.Now;
var result = await productRepository.UpdateAsync(product);
if (!result)
{
logger.LogError("商品状态更新失败ID: {Id}", id);
throw new BusinessException("更新商品状态失败", 500);
}
logger.LogInformation("商品上下架状态更新成功ID: {Id}, SaleStatus: {SaleStatus}", id, product.Status);
}
}

View File

@ -170,15 +170,14 @@ public class UsersService(
/// <summary>
/// 更新用户状态
/// </summary>
public async Task<BaseResponse> UpdateStatusAsync(long id, UpdateUserStatusInput input)
public async Task<BaseResponse> UpdateStatusAsync(long id)
{
var exists = await Queryable().AnyAsync(u => u.Id == id);
if (!exists)
var exists = await usersRepository.GetByIdAsync(id);
if (exists == null)
{
return BaseResponse.Fail("用户不存在");
}
var statusValue = input.Status == 1 ? UserStatusEnum.Active : UserStatusEnum.Disabled;
var statusValue = exists.Status == (int)UserStatusEnum.Active ? UserStatusEnum.Disabled : UserStatusEnum.Active;
var result = await UpdateAsync(
u => new Users { Status = (int)statusValue },
u => u.Id == id

View File

@ -45,7 +45,7 @@ public class WxMallService(
public async Task<List<WxProductOutput>> GetProductsAsync(long userId, string? type = null)
{
var query = exchangeRecordRepository.Context.Queryable<Product>()
.Where(p => !p.IsDeleted && p.IsActive && p.SaleStatus == "OnSale")
.Where(p => !p.IsDeleted && p.IsActive && p.Status == (int)ProductStatusEnum.OnSale)
.WhereIF(!string.IsNullOrEmpty(type), p => p.Type.ToString() == type)
.OrderByDescending(p => p.CreatedAt);
@ -53,7 +53,7 @@ public class WxMallService(
// 批量提取 PetBg 商品的 SkinId
var skinProductMap = products
.Where(p => p.Type == ProductTypeEnum.PetBg)
.Where(p => p.Type == ProductTypeEnum.PetSkin)
.Select(p => new { ProductId = p.Id, SkinId = GetSkinIdFromMetaData(p.MetaData) })
.Where(x => x.SkinId > 0)
.ToList();
@ -122,13 +122,13 @@ public class WxMallService(
public async Task<WxProductOutput?> GetProductDetailAsync(long userId, long productId)
{
var product = await exchangeRecordRepository.Context.Queryable<Product>()
.Where(p => p.Id == productId && !p.IsDeleted && p.IsActive && p.SaleStatus == "OnSale")
.Where(p => p.Id == productId && !p.IsDeleted && p.IsActive && p.Status == (int)ProductStatusEnum.OnSale)
.FirstAsync();
if (product == null) return null;
PetSkinBrief? skinBrief = null;
if (product.Type == ProductTypeEnum.PetBg)
if (product.Type == ProductTypeEnum.PetSkin)
{
var skinId = GetSkinIdFromMetaData(product.MetaData);
if (skinId > 0)
@ -190,7 +190,7 @@ public class WxMallService(
// 查询商品
var product = await exchangeRecordRepository.Context.Queryable<Product>()
.Where(p => p.Id == input.ProductId && !p.IsDeleted && p.IsActive && p.SaleStatus == "OnSale")
.Where(p => p.Id == input.ProductId && !p.IsDeleted && p.IsActive && p.Status == (int)ProductStatusEnum.OnSale)
.FirstAsync();
if (product == null)