refactor: 统一业务异常处理,标准化结果码和错误响应
1. 新增并完善ResultCode枚举,补充标准HTTP状态码对应的业务状态码 2. 重构BusinessException,新增基于ResultCode的构造函数和ThrowIf扩展方法 3. 替换所有硬编码的HTTP状态码为统一的ResultCode枚举 4. 优化全局异常中间件,根据业务状态码映射对应HTTP状态码并规范化JSON响应 5. 修复OssImageHelper和AutoDotCodeConsumer中的OSS文件处理逻辑 6. 新增用户答题快照实体类 7. 清理废弃的宠物模块迁移脚本
This commit is contained in:
@ -13,6 +13,14 @@ public class GlobalExceptionMiddleware : IMiddleware
|
|||||||
{
|
{
|
||||||
private readonly ILogger<GlobalExceptionMiddleware> _logger;
|
private readonly ILogger<GlobalExceptionMiddleware> _logger;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// JSON序列化选项(camelCase,与Controller保持一致)
|
||||||
|
/// </summary>
|
||||||
|
private static readonly JsonSerializerOptions JsonOptions = new()
|
||||||
|
{
|
||||||
|
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
|
||||||
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 构造函数
|
/// 构造函数
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -35,7 +43,7 @@ public class GlobalExceptionMiddleware : IMiddleware
|
|||||||
}
|
}
|
||||||
catch (BusinessException ex)
|
catch (BusinessException ex)
|
||||||
{
|
{
|
||||||
_logger.LogWarning(ex, "业务异常:{Message}", ex.Message);
|
_logger.LogWarning(ex, "业务异常:{Message},状态码:{ResultCode}", ex.Message, ex.ResultCode);
|
||||||
await HandleBusinessExceptionAsync(context, ex);
|
await HandleBusinessExceptionAsync(context, ex);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@ -46,17 +54,17 @@ public class GlobalExceptionMiddleware : IMiddleware
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 处理业务异常
|
/// 处理业务异常(按业务状态码映射HTTP状态码)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="context">HTTP上下文</param>
|
/// <param name="context">HTTP上下文</param>
|
||||||
/// <param name="ex">业务异常</param>
|
/// <param name="ex">业务异常</param>
|
||||||
private static async Task HandleBusinessExceptionAsync(HttpContext context, BusinessException ex)
|
private static async Task HandleBusinessExceptionAsync(HttpContext context, BusinessException ex)
|
||||||
{
|
{
|
||||||
context.Response.ContentType = "application/json";
|
context.Response.ContentType = "application/json";
|
||||||
context.Response.StatusCode = StatusCodes.Status400BadRequest;
|
context.Response.StatusCode = GetHttpStatusCode(ex.ResultCode);
|
||||||
|
|
||||||
var response = BaseResponse<object>.Fail(ResultCode.FAIL,ex.Message);
|
var response = BaseResponse<object>.Fail(ex.ResultCode, ex.Message);
|
||||||
var json = JsonSerializer.Serialize(response);
|
var json = JsonSerializer.Serialize(response, JsonOptions);
|
||||||
|
|
||||||
await context.Response.WriteAsync(json);
|
await context.Response.WriteAsync(json);
|
||||||
}
|
}
|
||||||
@ -71,9 +79,32 @@ public class GlobalExceptionMiddleware : IMiddleware
|
|||||||
context.Response.ContentType = "application/json";
|
context.Response.ContentType = "application/json";
|
||||||
context.Response.StatusCode = StatusCodes.Status500InternalServerError;
|
context.Response.StatusCode = StatusCodes.Status500InternalServerError;
|
||||||
|
|
||||||
var response = BaseResponse<object>.Fail("系统内部错误,请稍后重试");
|
var response = BaseResponse<object>.Fail(ResultCode.GLOBAL_ERROR, "系统内部错误,请稍后重试");
|
||||||
var json = JsonSerializer.Serialize(response);
|
var json = JsonSerializer.Serialize(response, JsonOptions);
|
||||||
|
|
||||||
await context.Response.WriteAsync(json);
|
await context.Response.WriteAsync(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 根据业务状态码获取对应的HTTP状态码
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="resultCode">业务状态码</param>
|
||||||
|
/// <returns>HTTP状态码</returns>
|
||||||
|
private static int GetHttpStatusCode(ResultCode resultCode)
|
||||||
|
{
|
||||||
|
return resultCode switch
|
||||||
|
{
|
||||||
|
ResultCode.DENY => StatusCodes.Status401Unauthorized,
|
||||||
|
ResultCode.FORBIDDEN => StatusCodes.Status403Forbidden,
|
||||||
|
ResultCode.NOT_FOUND => StatusCodes.Status404NotFound,
|
||||||
|
ResultCode.BAD_REQUEST => StatusCodes.Status400BadRequest,
|
||||||
|
ResultCode.PARAM_ERROR => StatusCodes.Status400BadRequest,
|
||||||
|
ResultCode.CONFLICT => StatusCodes.Status409Conflict,
|
||||||
|
ResultCode.UNPROCESSABLE_ENTITY => StatusCodes.Status422UnprocessableEntity,
|
||||||
|
ResultCode.TOO_MANY_REQUESTS => StatusCodes.Status429TooManyRequests,
|
||||||
|
ResultCode.BAD_GATEWAY => StatusCodes.Status502BadGateway,
|
||||||
|
ResultCode.SERVICE_UNAVAILABLE => StatusCodes.Status503ServiceUnavailable,
|
||||||
|
_ => StatusCodes.Status400BadRequest
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,7 +24,7 @@ public class ModelValidActionFilterAttribute : ActionFilterAttribute
|
|||||||
errorDic.Add(key, errorStr);
|
errorDic.Add(key, errorStr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var result = new BaseResponse<Dictionary<string, string>>() { code = ResultCode.FAIL };
|
var result = new BaseResponse<Dictionary<string, string>>() { code = ResultCode.BAD_REQUEST };
|
||||||
|
|
||||||
result.message = string.Join("|", errorDic.Select(e => e.Value).Distinct());
|
result.message = string.Join("|", errorDic.Select(e => e.Value).Distinct());
|
||||||
result.result = errorDic;
|
result.result = errorDic;
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using QYZH.InteractiveMagazine.Common.Extensions;
|
using QYZH.InteractiveMagazine.Common.Extensions;
|
||||||
using QYZH.InteractiveMagazine.Models.Common;
|
using QYZH.InteractiveMagazine.Models.Common;
|
||||||
|
using QYZH.InteractiveMagazine.Models.Dto;
|
||||||
|
|
||||||
namespace QYZH.InteractiveMagazine.Infrastructure.OSS;
|
namespace QYZH.InteractiveMagazine.Infrastructure.OSS;
|
||||||
|
|
||||||
@ -87,7 +88,7 @@ public class OssImageHelper
|
|||||||
catch (Exception ex) when (ex is not BusinessException)
|
catch (Exception ex) when (ex is not BusinessException)
|
||||||
{
|
{
|
||||||
_logger.LogError(ex, "OSS 图片搬运异常,Source: {Source}, Target: {Target}", sourcePath, targetPath);
|
_logger.LogError(ex, "OSS 图片搬运异常,Source: {Source}, Target: {Target}", sourcePath, targetPath);
|
||||||
throw new BusinessException("图片搬运失败,请重试", 500);
|
throw new BusinessException("图片搬运失败,请重试", ResultCode.GLOBAL_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -7,6 +7,8 @@ using CSRedis;
|
|||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using QYZH.InteractiveMagazine.Common.Extensions;
|
using QYZH.InteractiveMagazine.Common.Extensions;
|
||||||
|
using QYZH.InteractiveMagazine.Models.Common;
|
||||||
|
using QYZH.InteractiveMagazine.Models.Dto;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using System.Web;
|
using System.Web;
|
||||||
|
|
||||||
@ -193,6 +195,53 @@ namespace QYZH.InteractiveMagazine.Infrastructure.OSS
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 判断对象是否存在
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public bool DoesObjectExist(string key)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (key.IsNull()) return false;
|
||||||
|
|
||||||
|
key = key.RemoveDomain();
|
||||||
|
key = HttpUtility.UrlDecode(key);
|
||||||
|
|
||||||
|
return _ossClient.DoesObjectExist(_ossOption.BucketName, key);
|
||||||
|
}
|
||||||
|
catch (OssException ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex.Message + ex.StackTrace);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取对象内容流
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public Stream? GetObjectStream(string key)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (key.IsNull()) return null;
|
||||||
|
|
||||||
|
key = key.RemoveDomain();
|
||||||
|
key = HttpUtility.UrlDecode(key);
|
||||||
|
|
||||||
|
var ossObject = _ossClient.GetObject(_ossOption.BucketName, key);
|
||||||
|
return ossObject.Content;
|
||||||
|
}
|
||||||
|
catch (OssException ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex.Message + ex.StackTrace);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 删除多个
|
/// 删除多个
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
using QYZH.InteractiveMagazine.Models.Dto;
|
||||||
|
|
||||||
namespace QYZH.InteractiveMagazine.Models.Common;
|
namespace QYZH.InteractiveMagazine.Models.Common;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -10,6 +12,11 @@ public class BusinessException : Exception
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public int Code { get; set; }
|
public int Code { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 业务状态码
|
||||||
|
/// </summary>
|
||||||
|
public ResultCode ResultCode { get; set; } = ResultCode.FAIL;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 无参构造函数
|
/// 无参构造函数
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -33,6 +40,18 @@ public class BusinessException : Exception
|
|||||||
public BusinessException(string message, int code) : base(message)
|
public BusinessException(string message, int code) : base(message)
|
||||||
{
|
{
|
||||||
Code = code;
|
Code = code;
|
||||||
|
ResultCode = System.Enum.IsDefined(typeof(ResultCode), code) ? (ResultCode)code : ResultCode.FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 构造函数(按业务状态码)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="message">异常消息</param>
|
||||||
|
/// <param name="resultCode">业务状态码</param>
|
||||||
|
public BusinessException(string message, ResultCode resultCode) : base(message)
|
||||||
|
{
|
||||||
|
ResultCode = resultCode;
|
||||||
|
Code = (int)resultCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -62,4 +81,15 @@ public class BusinessException : Exception
|
|||||||
throw new BusinessException(message);
|
throw new BusinessException(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 条件抛出业务异常(带业务状态码)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="isTrue">是否触发</param>
|
||||||
|
/// <param name="message">异常消息</param>
|
||||||
|
/// <param name="resultCode">业务状态码</param>
|
||||||
|
public static void ThrowIf(bool isTrue, string message, ResultCode resultCode)
|
||||||
|
{
|
||||||
|
if (isTrue) throw new BusinessException(message, resultCode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -195,5 +195,23 @@ public enum ResultCode
|
|||||||
FORBIDDEN = 403,
|
FORBIDDEN = 403,
|
||||||
|
|
||||||
[Description("Bad Request")]
|
[Description("Bad Request")]
|
||||||
BAD_REQUEST = 400
|
BAD_REQUEST = 400,
|
||||||
|
|
||||||
|
[Description("资源不存在")]
|
||||||
|
NOT_FOUND = 404,
|
||||||
|
|
||||||
|
[Description("冲突/重复提交")]
|
||||||
|
CONFLICT = 409,
|
||||||
|
|
||||||
|
[Description("业务规则校验失败")]
|
||||||
|
UNPROCESSABLE_ENTITY = 422,
|
||||||
|
|
||||||
|
[Description("请求过于频繁")]
|
||||||
|
TOO_MANY_REQUESTS = 429,
|
||||||
|
|
||||||
|
[Description("第三方服务异常")]
|
||||||
|
BAD_GATEWAY = 502,
|
||||||
|
|
||||||
|
[Description("服务不可用")]
|
||||||
|
SERVICE_UNAVAILABLE = 503
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,161 @@
|
|||||||
|
using SqlSugar;
|
||||||
|
|
||||||
|
namespace QYZH.InteractiveMagazine.Models.Entity
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Snapshot record for a user answer.
|
||||||
|
/// </summary>
|
||||||
|
[SugarTable("JournalPageTaskUserAnswerSnapshot")]
|
||||||
|
public class JournalPageTaskUserAnswerSnapshot : SqlSugarBaseEntity
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Source JournalPageTaskUserAnswer record Id.
|
||||||
|
/// </summary>
|
||||||
|
public long JournalPageTaskUserAnswerId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Journal Id.
|
||||||
|
/// </summary>
|
||||||
|
public long JournalId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Journal page Id.
|
||||||
|
/// </summary>
|
||||||
|
public long JournalPageId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Journal page task Id.
|
||||||
|
/// </summary>
|
||||||
|
public long JournalPageTaskId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Journal page task group Id.
|
||||||
|
/// </summary>
|
||||||
|
public long JournalPageTaskGroupId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// User Id.
|
||||||
|
/// </summary>
|
||||||
|
public long UserId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Answer result.
|
||||||
|
/// </summary>
|
||||||
|
public string? Result { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Points awarded.
|
||||||
|
/// </summary>
|
||||||
|
public float Points { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Growth points awarded.
|
||||||
|
/// </summary>
|
||||||
|
public float GrowthPoints { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Task score.
|
||||||
|
/// </summary>
|
||||||
|
public float Score { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Question answer image URL.
|
||||||
|
/// </summary>
|
||||||
|
public string? QuestionAnswerUrl { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Answer image URL.
|
||||||
|
/// </summary>
|
||||||
|
public string? AnswerUrl { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Page answer image URL.
|
||||||
|
/// </summary>
|
||||||
|
public string? PageAnswerUrl { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Optimistic concurrency revision.
|
||||||
|
/// </summary>
|
||||||
|
public int Revision { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Answer status.
|
||||||
|
/// </summary>
|
||||||
|
public int AnswerStatus { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Answer start time.
|
||||||
|
/// </summary>
|
||||||
|
public DateTime AnswerStartTime { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Answer end time.
|
||||||
|
/// </summary>
|
||||||
|
public DateTime AnswerEndTime { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Answer duration in seconds.
|
||||||
|
/// </summary>
|
||||||
|
public int AnswerSeconds { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Image recognition result.
|
||||||
|
/// </summary>
|
||||||
|
public int ImageRecognition { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Journal page number.
|
||||||
|
/// </summary>
|
||||||
|
public int JournalPageNum { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Modify count.
|
||||||
|
/// </summary>
|
||||||
|
public int Modify { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Last tag Id.
|
||||||
|
/// </summary>
|
||||||
|
public long LastTag { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Dot page number.
|
||||||
|
/// </summary>
|
||||||
|
public int DotPageNum { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Page result image URL.
|
||||||
|
/// </summary>
|
||||||
|
public string? PageResultUrl { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Question type.
|
||||||
|
/// </summary>
|
||||||
|
public string? Type { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Dot page number text.
|
||||||
|
/// </summary>
|
||||||
|
public string? DotPageNo { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Page answer dot image URL.
|
||||||
|
/// </summary>
|
||||||
|
public string? PageAnswerDotUrl { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Break count.
|
||||||
|
/// </summary>
|
||||||
|
public int BreakCount { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Break time records.
|
||||||
|
/// </summary>
|
||||||
|
public string? BreakTimes { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Assignment status.
|
||||||
|
/// </summary>
|
||||||
|
public string? AssignmentStatus { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -25,31 +25,31 @@ public class AdminAuthService(BaseRepository<AdminUser> adminUserRepository, ICo
|
|||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(input.UserName))
|
if (string.IsNullOrWhiteSpace(input.UserName))
|
||||||
{
|
{
|
||||||
throw new BusinessException("用户名不能为空", 400);
|
throw new BusinessException("用户名不能为空", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(input.Password))
|
if (string.IsNullOrWhiteSpace(input.Password))
|
||||||
{
|
{
|
||||||
throw new BusinessException("密码不能为空", 400);
|
throw new BusinessException("密码不能为空", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
var adminUser = await adminUserRepository.GetFirstAsync(a => a.UserName == input.UserName);
|
var adminUser = await adminUserRepository.GetFirstAsync(a => a.UserName == input.UserName);
|
||||||
if (adminUser == null)
|
if (adminUser == null)
|
||||||
{
|
{
|
||||||
logger.LogWarning("管理员登录失败,用户名不存在: {UserName}", input.UserName);
|
logger.LogWarning("管理员登录失败,用户名不存在: {UserName}", input.UserName);
|
||||||
throw new BusinessException("用户名或密码错误", 401);
|
throw new BusinessException("用户名或密码错误", ResultCode.DENY);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!BCrypt.Net.BCrypt.Verify(input.Password, adminUser.PasswordHash))
|
if (!BCrypt.Net.BCrypt.Verify(input.Password, adminUser.PasswordHash))
|
||||||
{
|
{
|
||||||
logger.LogWarning("管理员登录失败,密码错误: {UserName}", input.UserName);
|
logger.LogWarning("管理员登录失败,密码错误: {UserName}", input.UserName);
|
||||||
throw new BusinessException("用户名或密码错误", 401);
|
throw new BusinessException("用户名或密码错误", ResultCode.DENY);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (adminUser.Status != 1)
|
if (adminUser.Status != 1)
|
||||||
{
|
{
|
||||||
logger.LogWarning("管理员登录失败,账号已禁用: {UserName}", input.UserName);
|
logger.LogWarning("管理员登录失败,账号已禁用: {UserName}", input.UserName);
|
||||||
throw new BusinessException("账号已被禁用,请联系系统管理员", 403);
|
throw new BusinessException("账号已被禁用,请联系系统管理员", ResultCode.FORBIDDEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
var jwtSettings = GetJwtSettings();
|
var jwtSettings = GetJwtSettings();
|
||||||
@ -86,7 +86,7 @@ public class AdminAuthService(BaseRepository<AdminUser> adminUserRepository, ICo
|
|||||||
if (adminUser == null)
|
if (adminUser == null)
|
||||||
{
|
{
|
||||||
logger.LogWarning("未找到管理员,ID: {UserId}", userId);
|
logger.LogWarning("未找到管理员,ID: {UserId}", userId);
|
||||||
throw new BusinessException("用户不存在", 404);
|
throw new BusinessException("用户不存在", ResultCode.NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new AdminUserInfoOutput
|
return new AdminUserInfoOutput
|
||||||
@ -104,25 +104,25 @@ public class AdminAuthService(BaseRepository<AdminUser> adminUserRepository, ICo
|
|||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(oldPassword))
|
if (string.IsNullOrWhiteSpace(oldPassword))
|
||||||
{
|
{
|
||||||
throw new BusinessException("原密码不能为空", 400);
|
throw new BusinessException("原密码不能为空", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(newPassword))
|
if (string.IsNullOrWhiteSpace(newPassword))
|
||||||
{
|
{
|
||||||
throw new BusinessException("新密码不能为空", 400);
|
throw new BusinessException("新密码不能为空", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
var adminUser = await adminUserRepository.GetByIdAsync(userId);
|
var adminUser = await adminUserRepository.GetByIdAsync(userId);
|
||||||
if (adminUser == null)
|
if (adminUser == null)
|
||||||
{
|
{
|
||||||
logger.LogWarning("未找到管理员,ID: {UserId}", userId);
|
logger.LogWarning("未找到管理员,ID: {UserId}", userId);
|
||||||
throw new BusinessException("用户不存在", 404);
|
throw new BusinessException("用户不存在", ResultCode.NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!BCrypt.Net.BCrypt.Verify(oldPassword, adminUser.PasswordHash))
|
if (!BCrypt.Net.BCrypt.Verify(oldPassword, adminUser.PasswordHash))
|
||||||
{
|
{
|
||||||
logger.LogWarning("管理员修改密码失败,原密码错误,ID: {UserId}", userId);
|
logger.LogWarning("管理员修改密码失败,原密码错误,ID: {UserId}", userId);
|
||||||
throw new BusinessException("原密码错误", 400);
|
throw new BusinessException("原密码错误", ResultCode.DENY);
|
||||||
}
|
}
|
||||||
|
|
||||||
adminUser.PasswordHash = BCrypt.Net.BCrypt.HashPassword(newPassword);
|
adminUser.PasswordHash = BCrypt.Net.BCrypt.HashPassword(newPassword);
|
||||||
@ -130,7 +130,7 @@ public class AdminAuthService(BaseRepository<AdminUser> adminUserRepository, ICo
|
|||||||
var result = await adminUserRepository.UpdateAsync(adminUser);
|
var result = await adminUserRepository.UpdateAsync(adminUser);
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
throw new BusinessException("修改密码失败", 500);
|
throw new BusinessException("修改密码失败", ResultCode.GLOBAL_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
await RedisHelper.DelAsync($"{TokenKeyPrefix}:{userId}");
|
await RedisHelper.DelAsync($"{TokenKeyPrefix}:{userId}");
|
||||||
@ -151,7 +151,7 @@ public class AdminAuthService(BaseRepository<AdminUser> adminUserRepository, ICo
|
|||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(jwtSettings.SecretKey))
|
if (string.IsNullOrWhiteSpace(jwtSettings.SecretKey))
|
||||||
{
|
{
|
||||||
throw new BusinessException("JWT 配置不完整", 500);
|
throw new BusinessException("JWT 配置不完整", ResultCode.GLOBAL_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
return jwtSettings;
|
return jwtSettings;
|
||||||
|
|||||||
@ -27,12 +27,12 @@ public class AdminUserService(BaseRepository<AdminUser> adminUserRepository, ILo
|
|||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(input.UserName))
|
if (string.IsNullOrWhiteSpace(input.UserName))
|
||||||
{
|
{
|
||||||
throw new BusinessException("用户名不能为空", 400);
|
throw new BusinessException("用户名不能为空", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(input.Password))
|
if (string.IsNullOrWhiteSpace(input.Password))
|
||||||
{
|
{
|
||||||
throw new BusinessException("密码不能为空", 400);
|
throw new BusinessException("密码不能为空", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查用户名是否已存在
|
// 检查用户名是否已存在
|
||||||
@ -40,7 +40,7 @@ public class AdminUserService(BaseRepository<AdminUser> adminUserRepository, ILo
|
|||||||
if (existingUser != null)
|
if (existingUser != null)
|
||||||
{
|
{
|
||||||
logger.LogWarning("创建管理员失败,用户名已存在: {UserName}", input.UserName);
|
logger.LogWarning("创建管理员失败,用户名已存在: {UserName}", input.UserName);
|
||||||
throw new BusinessException("用户名已存在", 400);
|
throw new BusinessException("用户名已存在", ResultCode.CONFLICT);
|
||||||
}
|
}
|
||||||
|
|
||||||
var adminUser = new AdminUser
|
var adminUser = new AdminUser
|
||||||
@ -60,7 +60,7 @@ public class AdminUserService(BaseRepository<AdminUser> adminUserRepository, ILo
|
|||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
logger.LogError("管理员创建失败,用户名: {UserName}", input.UserName);
|
logger.LogError("管理员创建失败,用户名: {UserName}", input.UserName);
|
||||||
throw new BusinessException("创建管理员失败", 500);
|
throw new BusinessException("创建管理员失败", ResultCode.GLOBAL_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.LogInformation("管理员创建成功,用户名: {UserName}, ID: {Id}", input.UserName, adminUser.Id);
|
logger.LogInformation("管理员创建成功,用户名: {UserName}, ID: {Id}", input.UserName, adminUser.Id);
|
||||||
@ -79,7 +79,7 @@ public class AdminUserService(BaseRepository<AdminUser> adminUserRepository, ILo
|
|||||||
if (adminUser == null)
|
if (adminUser == null)
|
||||||
{
|
{
|
||||||
logger.LogWarning("未找到要更新的管理员,ID: {Id}", id);
|
logger.LogWarning("未找到要更新的管理员,ID: {Id}", id);
|
||||||
throw new BusinessException("管理员不存在", 404);
|
throw new BusinessException("管理员不存在", ResultCode.NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果用户名有变更,检查是否与其他用户重复
|
// 如果用户名有变更,检查是否与其他用户重复
|
||||||
@ -89,7 +89,7 @@ public class AdminUserService(BaseRepository<AdminUser> adminUserRepository, ILo
|
|||||||
if (existingUser != null && existingUser.Id != id)
|
if (existingUser != null && existingUser.Id != id)
|
||||||
{
|
{
|
||||||
logger.LogWarning("更新管理员失败,用户名已存在: {UserName}", input.UserName);
|
logger.LogWarning("更新管理员失败,用户名已存在: {UserName}", input.UserName);
|
||||||
throw new BusinessException("用户名已存在", 400);
|
throw new BusinessException("用户名已存在", ResultCode.CONFLICT);
|
||||||
}
|
}
|
||||||
|
|
||||||
adminUser.UserName = input.UserName.Trim();
|
adminUser.UserName = input.UserName.Trim();
|
||||||
@ -111,7 +111,7 @@ public class AdminUserService(BaseRepository<AdminUser> adminUserRepository, ILo
|
|||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
logger.LogError("管理员更新失败,ID: {Id}", id);
|
logger.LogError("管理员更新失败,ID: {Id}", id);
|
||||||
throw new BusinessException("更新管理员失败", 500);
|
throw new BusinessException("更新管理员失败", ResultCode.GLOBAL_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.LogInformation("管理员更新成功,ID: {Id}", id);
|
logger.LogInformation("管理员更新成功,ID: {Id}", id);
|
||||||
@ -130,14 +130,14 @@ public class AdminUserService(BaseRepository<AdminUser> adminUserRepository, ILo
|
|||||||
if (adminUser == null)
|
if (adminUser == null)
|
||||||
{
|
{
|
||||||
logger.LogWarning("未找到要删除的管理员,ID: {Id}", id);
|
logger.LogWarning("未找到要删除的管理员,ID: {Id}", id);
|
||||||
throw new BusinessException("管理员不存在", 404);
|
throw new BusinessException("管理员不存在", ResultCode.NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = await adminUserRepository.DeleteByIdAsync(id);
|
var result = await adminUserRepository.DeleteByIdAsync(id);
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
logger.LogError("管理员删除失败,ID: {Id}", id);
|
logger.LogError("管理员删除失败,ID: {Id}", id);
|
||||||
throw new BusinessException("删除管理员失败", 500);
|
throw new BusinessException("删除管理员失败", ResultCode.GLOBAL_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.LogInformation("管理员删除成功,ID: {Id}", id);
|
logger.LogInformation("管理员删除成功,ID: {Id}", id);
|
||||||
@ -154,7 +154,7 @@ public class AdminUserService(BaseRepository<AdminUser> adminUserRepository, ILo
|
|||||||
if (adminUser == null)
|
if (adminUser == null)
|
||||||
{
|
{
|
||||||
logger.LogWarning("未找到管理员,ID: {Id}", id);
|
logger.LogWarning("未找到管理员,ID: {Id}", id);
|
||||||
throw new BusinessException("管理员不存在", 404);
|
throw new BusinessException("管理员不存在", ResultCode.NOT_FOUND);
|
||||||
}
|
}
|
||||||
return new AdminUserOutput
|
return new AdminUserOutput
|
||||||
{
|
{
|
||||||
@ -178,12 +178,12 @@ public class AdminUserService(BaseRepository<AdminUser> adminUserRepository, ILo
|
|||||||
|
|
||||||
if (input.PageIndex <= 0)
|
if (input.PageIndex <= 0)
|
||||||
{
|
{
|
||||||
throw new BusinessException("页码必须大于0", 400);
|
throw new BusinessException("页码必须大于0", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input.PageSize <= 0 || input.PageSize > 100)
|
if (input.PageSize <= 0 || input.PageSize > 100)
|
||||||
{
|
{
|
||||||
throw new BusinessException("每页条数必须在1-100之间", 400);
|
throw new BusinessException("每页条数必须在1-100之间", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
RefAsync<int> totalNumber = 0;
|
RefAsync<int> totalNumber = 0;
|
||||||
var pageResult = await adminUserRepository.Queryable()
|
var pageResult = await adminUserRepository.Queryable()
|
||||||
@ -215,7 +215,7 @@ public class AdminUserService(BaseRepository<AdminUser> adminUserRepository, ILo
|
|||||||
if (adminUser == null)
|
if (adminUser == null)
|
||||||
{
|
{
|
||||||
logger.LogWarning("未找到要更新状态的管理员,ID: {Id}", id);
|
logger.LogWarning("未找到要更新状态的管理员,ID: {Id}", id);
|
||||||
throw new BusinessException("管理员不存在", 404);
|
throw new BusinessException("管理员不存在", ResultCode.NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
adminUser.Status = adminUser.Status==(int)DefaultStatusEnum.Active?(int)DefaultStatusEnum.Inactive:(int)DefaultStatusEnum.Active;
|
adminUser.Status = adminUser.Status==(int)DefaultStatusEnum.Active?(int)DefaultStatusEnum.Inactive:(int)DefaultStatusEnum.Active;
|
||||||
@ -226,7 +226,7 @@ public class AdminUserService(BaseRepository<AdminUser> adminUserRepository, ILo
|
|||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
logger.LogError("管理员状态更新失败,ID: {Id}", id);
|
logger.LogError("管理员状态更新失败,ID: {Id}", id);
|
||||||
throw new BusinessException("更新管理员状态失败", 500);
|
throw new BusinessException("更新管理员状态失败", ResultCode.GLOBAL_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.LogInformation("管理员状态更新成功,ID: {Id}", id);
|
logger.LogInformation("管理员状态更新成功,ID: {Id}", id);
|
||||||
|
|||||||
@ -25,24 +25,24 @@ public class AiBasePromptService(
|
|||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(input.PromptKey))
|
if (string.IsNullOrWhiteSpace(input.PromptKey))
|
||||||
{
|
{
|
||||||
throw new BusinessException("配置标识不能为空", 400);
|
throw new BusinessException("配置标识不能为空", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(input.PromptName))
|
if (string.IsNullOrWhiteSpace(input.PromptName))
|
||||||
{
|
{
|
||||||
throw new BusinessException("配置名称不能为空", 400);
|
throw new BusinessException("配置名称不能为空", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(input.PromptTemplate))
|
if (string.IsNullOrWhiteSpace(input.PromptTemplate))
|
||||||
{
|
{
|
||||||
throw new BusinessException("Prompt模板内容不能为空", 400);
|
throw new BusinessException("Prompt模板内容不能为空", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查PromptKey是否已存在
|
// 检查PromptKey是否已存在
|
||||||
var exists = await promptRepository.IsAnyAsync(p => p.PromptKey == input.PromptKey.Trim());
|
var exists = await promptRepository.IsAnyAsync(p => p.PromptKey == input.PromptKey.Trim());
|
||||||
if (exists)
|
if (exists)
|
||||||
{
|
{
|
||||||
throw new BusinessException($"配置标识 '{input.PromptKey.Trim()}' 已存在", 400);
|
throw new BusinessException($"配置标识 '{input.PromptKey.Trim()}' 已存在", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
var entity = new AiBasePrompt
|
var entity = new AiBasePrompt
|
||||||
@ -64,7 +64,7 @@ public class AiBasePromptService(
|
|||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
logger.LogError("Prompt配置创建失败,PromptKey: {PromptKey}", input.PromptKey);
|
logger.LogError("Prompt配置创建失败,PromptKey: {PromptKey}", input.PromptKey);
|
||||||
throw new BusinessException("创建Prompt配置失败", 500);
|
throw new BusinessException("创建Prompt配置失败", ResultCode.GLOBAL_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.LogInformation("Prompt配置创建成功,PromptKey: {PromptKey}, ID: {Id}", input.PromptKey, entity.Id);
|
logger.LogInformation("Prompt配置创建成功,PromptKey: {PromptKey}, ID: {Id}", input.PromptKey, entity.Id);
|
||||||
@ -97,29 +97,29 @@ public class AiBasePromptService(
|
|||||||
if (entity == null)
|
if (entity == null)
|
||||||
{
|
{
|
||||||
logger.LogWarning("未找到要更新的Prompt配置,ID: {Id}", id);
|
logger.LogWarning("未找到要更新的Prompt配置,ID: {Id}", id);
|
||||||
throw new BusinessException("Prompt配置不存在", 404);
|
throw new BusinessException("Prompt配置不存在", ResultCode.NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(input.PromptKey))
|
if (string.IsNullOrWhiteSpace(input.PromptKey))
|
||||||
{
|
{
|
||||||
throw new BusinessException("配置标识不能为空", 400);
|
throw new BusinessException("配置标识不能为空", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(input.PromptName))
|
if (string.IsNullOrWhiteSpace(input.PromptName))
|
||||||
{
|
{
|
||||||
throw new BusinessException("配置名称不能为空", 400);
|
throw new BusinessException("配置名称不能为空", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(input.PromptTemplate))
|
if (string.IsNullOrWhiteSpace(input.PromptTemplate))
|
||||||
{
|
{
|
||||||
throw new BusinessException("Prompt模板内容不能为空", 400);
|
throw new BusinessException("Prompt模板内容不能为空", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查PromptKey是否被其他记录占用
|
// 检查PromptKey是否被其他记录占用
|
||||||
var exists = await promptRepository.IsAnyAsync(p => p.PromptKey == input.PromptKey.Trim() && p.Id != id);
|
var exists = await promptRepository.IsAnyAsync(p => p.PromptKey == input.PromptKey.Trim() && p.Id != id);
|
||||||
if (exists)
|
if (exists)
|
||||||
{
|
{
|
||||||
throw new BusinessException($"配置标识 '{input.PromptKey.Trim()}' 已被其他配置使用", 400);
|
throw new BusinessException($"配置标识 '{input.PromptKey.Trim()}' 已被其他配置使用", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
entity.PromptKey = input.PromptKey.Trim();
|
entity.PromptKey = input.PromptKey.Trim();
|
||||||
@ -135,7 +135,7 @@ public class AiBasePromptService(
|
|||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
logger.LogError("Prompt配置更新失败,ID: {Id}", id);
|
logger.LogError("Prompt配置更新失败,ID: {Id}", id);
|
||||||
throw new BusinessException("更新Prompt配置失败", 500);
|
throw new BusinessException("更新Prompt配置失败", ResultCode.GLOBAL_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.LogInformation("Prompt配置更新成功,ID: {Id}", id);
|
logger.LogInformation("Prompt配置更新成功,ID: {Id}", id);
|
||||||
@ -168,14 +168,14 @@ public class AiBasePromptService(
|
|||||||
if (entity == null)
|
if (entity == null)
|
||||||
{
|
{
|
||||||
logger.LogWarning("未找到要删除的Prompt配置,ID: {Id}", id);
|
logger.LogWarning("未找到要删除的Prompt配置,ID: {Id}", id);
|
||||||
throw new BusinessException("Prompt配置不存在", 404);
|
throw new BusinessException("Prompt配置不存在", ResultCode.NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = await promptRepository.DeleteByIdAsync(id);
|
var result = await promptRepository.DeleteByIdAsync(id);
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
logger.LogError("Prompt配置删除失败,ID: {Id}", id);
|
logger.LogError("Prompt配置删除失败,ID: {Id}", id);
|
||||||
throw new BusinessException("删除Prompt配置失败", 500);
|
throw new BusinessException("删除Prompt配置失败", ResultCode.GLOBAL_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.LogInformation("Prompt配置删除成功,ID: {Id}", id);
|
logger.LogInformation("Prompt配置删除成功,ID: {Id}", id);
|
||||||
@ -192,7 +192,7 @@ public class AiBasePromptService(
|
|||||||
if (entity == null)
|
if (entity == null)
|
||||||
{
|
{
|
||||||
logger.LogWarning("未找到Prompt配置,ID: {Id}", id);
|
logger.LogWarning("未找到Prompt配置,ID: {Id}", id);
|
||||||
throw new BusinessException("Prompt配置不存在", 404);
|
throw new BusinessException("Prompt配置不存在", ResultCode.NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new AiBasePromptOutput
|
return new AiBasePromptOutput
|
||||||
@ -221,12 +221,12 @@ public class AiBasePromptService(
|
|||||||
|
|
||||||
if (input.PageIndex <= 0)
|
if (input.PageIndex <= 0)
|
||||||
{
|
{
|
||||||
throw new BusinessException("页码必须大于0", 400);
|
throw new BusinessException("页码必须大于0", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input.PageSize <= 0 || input.PageSize > 100)
|
if (input.PageSize <= 0 || input.PageSize > 100)
|
||||||
{
|
{
|
||||||
throw new BusinessException("每页条数必须在1-100之间", 400);
|
throw new BusinessException("每页条数必须在1-100之间", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
RefAsync<int> totalNumber = 0;
|
RefAsync<int> totalNumber = 0;
|
||||||
@ -296,7 +296,7 @@ public class AiBasePromptService(
|
|||||||
if (entity == null)
|
if (entity == null)
|
||||||
{
|
{
|
||||||
logger.LogWarning("未找到要切换状态的Prompt配置,ID: {Id}", id);
|
logger.LogWarning("未找到要切换状态的Prompt配置,ID: {Id}", id);
|
||||||
throw new BusinessException("Prompt配置不存在", 404);
|
throw new BusinessException("Prompt配置不存在", ResultCode.NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
entity.Status = entity.Status == 1 ? 0 : 1;
|
entity.Status = entity.Status == 1 ? 0 : 1;
|
||||||
@ -307,7 +307,7 @@ public class AiBasePromptService(
|
|||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
logger.LogError("Prompt配置状态切换失败,ID: {Id}", id);
|
logger.LogError("Prompt配置状态切换失败,ID: {Id}", id);
|
||||||
throw new BusinessException("切换Prompt状态失败", 500);
|
throw new BusinessException("切换Prompt状态失败", ResultCode.GLOBAL_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.LogInformation("Prompt配置状态切换成功,ID: {Id}, Status: {Status}", id, entity.Status);
|
logger.LogInformation("Prompt配置状态切换成功,ID: {Id}, Status: {Status}", id, entity.Status);
|
||||||
|
|||||||
@ -83,7 +83,7 @@ public class AiChatService(
|
|||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(input.Message))
|
if (string.IsNullOrWhiteSpace(input.Message))
|
||||||
{
|
{
|
||||||
throw new BusinessException("消息内容不能为空", 400);
|
throw new BusinessException("消息内容不能为空", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
var apiKey = configuration["AiChat:ApiKey"];
|
var apiKey = configuration["AiChat:ApiKey"];
|
||||||
@ -95,7 +95,7 @@ public class AiChatService(
|
|||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(apiKey) || string.IsNullOrWhiteSpace(baseUrl) || string.IsNullOrWhiteSpace(model))
|
if (string.IsNullOrWhiteSpace(apiKey) || string.IsNullOrWhiteSpace(baseUrl) || string.IsNullOrWhiteSpace(model))
|
||||||
{
|
{
|
||||||
throw new BusinessException("AI聊天服务配置不完整,请检查 AiChat 配置节", 500);
|
throw new BusinessException("AI聊天服务配置不完整,请检查 AiChat 配置节", ResultCode.GLOBAL_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.LogInformation("开始调用AI聊天服务(流式),消息长度:{Length}", input.Message.Length);
|
logger.LogInformation("开始调用AI聊天服务(流式),消息长度:{Length}", input.Message.Length);
|
||||||
@ -132,7 +132,7 @@ public class AiChatService(
|
|||||||
{
|
{
|
||||||
var errorContent = await response.Content.ReadAsStringAsync(cancellationToken);
|
var errorContent = await response.Content.ReadAsStringAsync(cancellationToken);
|
||||||
logger.LogError("AI聊天服务调用失败,状态码:{StatusCode},响应:{Response}", response.StatusCode, errorContent);
|
logger.LogError("AI聊天服务调用失败,状态码:{StatusCode},响应:{Response}", response.StatusCode, errorContent);
|
||||||
throw new BusinessException($"AI服务调用失败:{response.StatusCode}", 500);
|
throw new BusinessException($"AI服务调用失败:{response.StatusCode}", ResultCode.GLOBAL_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 流式读取响应体
|
// 流式读取响应体
|
||||||
|
|||||||
@ -27,17 +27,17 @@ public class CheckInConfigService(
|
|||||||
|
|
||||||
if (input.DayNumber <= 0)
|
if (input.DayNumber <= 0)
|
||||||
{
|
{
|
||||||
throw new BusinessException("连续签到天数必须大于0", 400);
|
throw new BusinessException("连续签到天数必须大于0", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input.RewardPoints < 0)
|
if (input.RewardPoints < 0)
|
||||||
{
|
{
|
||||||
throw new BusinessException("奖励积分不能为负数", 400);
|
throw new BusinessException("奖励积分不能为负数", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input.BonusPoints < 0)
|
if (input.BonusPoints < 0)
|
||||||
{
|
{
|
||||||
throw new BusinessException("额外奖励积分不能为负数", 400);
|
throw new BusinessException("额外奖励积分不能为负数", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查同类型下是否已存在相同天数配置
|
// 检查同类型下是否已存在相同天数配置
|
||||||
@ -47,7 +47,7 @@ public class CheckInConfigService(
|
|||||||
|
|
||||||
if (exists)
|
if (exists)
|
||||||
{
|
{
|
||||||
throw new BusinessException($"该类型下已存在连续{input.DayNumber}天的配置", 400);
|
throw new BusinessException($"该类型下已存在连续{input.DayNumber}天的配置", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
var config = new CheckInConfig
|
var config = new CheckInConfig
|
||||||
@ -67,7 +67,7 @@ public class CheckInConfigService(
|
|||||||
var result = await checkInConfigRepository.InsertAsync(config);
|
var result = await checkInConfigRepository.InsertAsync(config);
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
throw new BusinessException("创建签到配置失败", 500);
|
throw new BusinessException("创建签到配置失败", ResultCode.GLOBAL_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.LogInformation("签到配置创建成功,ID: {Id}", config.Id);
|
logger.LogInformation("签到配置创建成功,ID: {Id}", config.Id);
|
||||||
@ -85,22 +85,22 @@ public class CheckInConfigService(
|
|||||||
if (config == null)
|
if (config == null)
|
||||||
{
|
{
|
||||||
logger.LogWarning("未找到要更新的签到配置,ID: {Id}", id);
|
logger.LogWarning("未找到要更新的签到配置,ID: {Id}", id);
|
||||||
throw new BusinessException("签到配置不存在", 404);
|
throw new BusinessException("签到配置不存在", ResultCode.NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input.DayNumber <= 0)
|
if (input.DayNumber <= 0)
|
||||||
{
|
{
|
||||||
throw new BusinessException("连续签到天数必须大于0", 400);
|
throw new BusinessException("连续签到天数必须大于0", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input.RewardPoints < 0)
|
if (input.RewardPoints < 0)
|
||||||
{
|
{
|
||||||
throw new BusinessException("奖励积分不能为负数", 400);
|
throw new BusinessException("奖励积分不能为负数", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input.BonusPoints < 0)
|
if (input.BonusPoints < 0)
|
||||||
{
|
{
|
||||||
throw new BusinessException("额外奖励积分不能为负数", 400);
|
throw new BusinessException("额外奖励积分不能为负数", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查同类型下是否已存在相同天数配置(排除自身)
|
// 检查同类型下是否已存在相同天数配置(排除自身)
|
||||||
@ -110,7 +110,7 @@ public class CheckInConfigService(
|
|||||||
|
|
||||||
if (exists)
|
if (exists)
|
||||||
{
|
{
|
||||||
throw new BusinessException($"该类型下已存在连续{input.DayNumber}天的配置", 400);
|
throw new BusinessException($"该类型下已存在连续{input.DayNumber}天的配置", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
config.DayNumber = input.DayNumber;
|
config.DayNumber = input.DayNumber;
|
||||||
@ -123,7 +123,7 @@ public class CheckInConfigService(
|
|||||||
var updateResult = await checkInConfigRepository.UpdateAsync(config);
|
var updateResult = await checkInConfigRepository.UpdateAsync(config);
|
||||||
if (!updateResult)
|
if (!updateResult)
|
||||||
{
|
{
|
||||||
throw new BusinessException("更新签到配置失败", 500);
|
throw new BusinessException("更新签到配置失败", ResultCode.GLOBAL_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.LogInformation("签到配置更新成功,ID: {Id}", id);
|
logger.LogInformation("签到配置更新成功,ID: {Id}", id);
|
||||||
@ -141,7 +141,7 @@ public class CheckInConfigService(
|
|||||||
if (config == null)
|
if (config == null)
|
||||||
{
|
{
|
||||||
logger.LogWarning("未找到要删除的签到配置,ID: {Id}", id);
|
logger.LogWarning("未找到要删除的签到配置,ID: {Id}", id);
|
||||||
throw new BusinessException("签到配置不存在", 404);
|
throw new BusinessException("签到配置不存在", ResultCode.NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = await checkInConfigRepository.Context.Updateable<CheckInConfig>()
|
var result = await checkInConfigRepository.Context.Updateable<CheckInConfig>()
|
||||||
@ -156,7 +156,7 @@ public class CheckInConfigService(
|
|||||||
|
|
||||||
if (result <= 0)
|
if (result <= 0)
|
||||||
{
|
{
|
||||||
throw new BusinessException("删除签到配置失败", 500);
|
throw new BusinessException("删除签到配置失败", ResultCode.GLOBAL_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.LogInformation("签到配置删除成功,ID: {Id}", id);
|
logger.LogInformation("签到配置删除成功,ID: {Id}", id);
|
||||||
@ -170,7 +170,7 @@ public class CheckInConfigService(
|
|||||||
var config = await checkInConfigRepository.GetByIdAsync(id);
|
var config = await checkInConfigRepository.GetByIdAsync(id);
|
||||||
if (config == null)
|
if (config == null)
|
||||||
{
|
{
|
||||||
throw new BusinessException("签到配置不存在", 404);
|
throw new BusinessException("签到配置不存在", ResultCode.NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
return MapToOutput(config);
|
return MapToOutput(config);
|
||||||
@ -185,12 +185,12 @@ public class CheckInConfigService(
|
|||||||
|
|
||||||
if (input.PageIndex <= 0)
|
if (input.PageIndex <= 0)
|
||||||
{
|
{
|
||||||
throw new BusinessException("页码必须大于0", 400);
|
throw new BusinessException("页码必须大于0", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input.PageSize <= 0 || input.PageSize > 100)
|
if (input.PageSize <= 0 || input.PageSize > 100)
|
||||||
{
|
{
|
||||||
throw new BusinessException("每页条数必须在1-100之间", 400);
|
throw new BusinessException("每页条数必须在1-100之间", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
RefAsync<int> totalNumber = 0;
|
RefAsync<int> totalNumber = 0;
|
||||||
@ -217,7 +217,7 @@ public class CheckInConfigService(
|
|||||||
if (config == null)
|
if (config == null)
|
||||||
{
|
{
|
||||||
logger.LogWarning("未找到要更新状态的签到配置,ID: {Id}", id);
|
logger.LogWarning("未找到要更新状态的签到配置,ID: {Id}", id);
|
||||||
throw new BusinessException("签到配置不存在", 404);
|
throw new BusinessException("签到配置不存在", ResultCode.NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
config.Status = config.Status == (int)DefaultStatusEnum.Active
|
config.Status = config.Status == (int)DefaultStatusEnum.Active
|
||||||
@ -230,7 +230,7 @@ public class CheckInConfigService(
|
|||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
logger.LogError("签到配置状态更新失败,ID: {Id}", id);
|
logger.LogError("签到配置状态更新失败,ID: {Id}", id);
|
||||||
throw new BusinessException("更新签到配置状态失败", 500);
|
throw new BusinessException("更新签到配置状态失败", ResultCode.GLOBAL_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.LogInformation("签到配置状态更新成功,ID: {Id}, Status: {Status}", id, config.Status);
|
logger.LogInformation("签到配置状态更新成功,ID: {Id}, Status: {Status}", id, config.Status);
|
||||||
|
|||||||
@ -2,6 +2,7 @@ using Microsoft.Extensions.Logging;
|
|||||||
using QYZH.InteractiveMagazine.Common.Extensions;
|
using QYZH.InteractiveMagazine.Common.Extensions;
|
||||||
using QYZH.InteractiveMagazine.IService;
|
using QYZH.InteractiveMagazine.IService;
|
||||||
using QYZH.InteractiveMagazine.Models.Common;
|
using QYZH.InteractiveMagazine.Models.Common;
|
||||||
|
using QYZH.InteractiveMagazine.Models.Dto;
|
||||||
using QYZH.InteractiveMagazine.Models.Dto.CheckIn;
|
using QYZH.InteractiveMagazine.Models.Dto.CheckIn;
|
||||||
using QYZH.InteractiveMagazine.Models.Dto.Compensation;
|
using QYZH.InteractiveMagazine.Models.Dto.Compensation;
|
||||||
using QYZH.InteractiveMagazine.Models.Dto.Pet;
|
using QYZH.InteractiveMagazine.Models.Dto.Pet;
|
||||||
@ -44,7 +45,7 @@ public class CheckInService(
|
|||||||
|
|
||||||
if (alreadyCheckedIn)
|
if (alreadyCheckedIn)
|
||||||
{
|
{
|
||||||
throw new BusinessException("今日已签到,请明天再来", 400);
|
throw new BusinessException("今日已签到,请明天再来", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 计算连续签到天数
|
// 2. 计算连续签到天数
|
||||||
@ -60,7 +61,7 @@ public class CheckInService(
|
|||||||
|
|
||||||
if (user == null)
|
if (user == null)
|
||||||
{
|
{
|
||||||
throw new BusinessException("用户不存在", 404);
|
throw new BusinessException("用户不存在", ResultCode.NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5. 查询用户宠物(如果有)
|
// 5. 查询用户宠物(如果有)
|
||||||
@ -226,7 +227,7 @@ public class CheckInService(
|
|||||||
targetDate = targetDate.Date;
|
targetDate = targetDate.Date;
|
||||||
|
|
||||||
if (targetDate >= DateTime.Now.Date)
|
if (targetDate >= DateTime.Now.Date)
|
||||||
throw new BusinessException("只能补签过去的日期", 400);
|
throw new BusinessException("只能补签过去的日期", ResultCode.BAD_REQUEST);
|
||||||
|
|
||||||
// 检查目标日期是否已有签到记录
|
// 检查目标日期是否已有签到记录
|
||||||
var alreadyCheckedIn = await checkInRecordRepository.Context.Queryable<CheckInRecord>()
|
var alreadyCheckedIn = await checkInRecordRepository.Context.Queryable<CheckInRecord>()
|
||||||
@ -235,7 +236,7 @@ public class CheckInService(
|
|||||||
.AnyAsync();
|
.AnyAsync();
|
||||||
|
|
||||||
if (alreadyCheckedIn)
|
if (alreadyCheckedIn)
|
||||||
throw new BusinessException($"{targetDate:yyyy-MM-dd} 已签到,无需补签", 400);
|
throw new BusinessException($"{targetDate:yyyy-MM-dd} 已签到,无需补签", ResultCode.BAD_REQUEST);
|
||||||
|
|
||||||
// 检查用户背包中是否有补签卡
|
// 检查用户背包中是否有补签卡
|
||||||
var makeUpCard = await checkInRecordRepository.Context.Queryable<UserBag>()
|
var makeUpCard = await checkInRecordRepository.Context.Queryable<UserBag>()
|
||||||
@ -248,7 +249,7 @@ public class CheckInService(
|
|||||||
.FirstAsync();
|
.FirstAsync();
|
||||||
|
|
||||||
if (makeUpCard == null)
|
if (makeUpCard == null)
|
||||||
throw new BusinessException("补签卡不足,无法补签", 400);
|
throw new BusinessException("补签卡不足,无法补签", ResultCode.BAD_REQUEST);
|
||||||
|
|
||||||
// 查询用户信息
|
// 查询用户信息
|
||||||
var user = await checkInRecordRepository.Context.Queryable<Users>()
|
var user = await checkInRecordRepository.Context.Queryable<Users>()
|
||||||
@ -256,7 +257,7 @@ public class CheckInService(
|
|||||||
.FirstAsync();
|
.FirstAsync();
|
||||||
|
|
||||||
if (user == null)
|
if (user == null)
|
||||||
throw new BusinessException("用户不存在", 404);
|
throw new BusinessException("用户不存在", ResultCode.NOT_FOUND);
|
||||||
|
|
||||||
// 查询宠物
|
// 查询宠物
|
||||||
var pet = await checkInRecordRepository.Context.Queryable<UserPet>()
|
var pet = await checkInRecordRepository.Context.Queryable<UserPet>()
|
||||||
|
|||||||
@ -24,8 +24,8 @@ public class CommunityMessageService(BaseRepository<CommunityMessage> messageRep
|
|||||||
{
|
{
|
||||||
logger.LogInformation("正在查询社区消息列表,页码: {PageIndex}, 每页条数: {PageSize}", input.PageIndex, input.PageSize);
|
logger.LogInformation("正在查询社区消息列表,页码: {PageIndex}, 每页条数: {PageSize}", input.PageIndex, input.PageSize);
|
||||||
|
|
||||||
if (input.PageIndex <= 0) throw new BusinessException("页码必须大于0", 400);
|
if (input.PageIndex <= 0) throw new BusinessException("页码必须大于0", ResultCode.BAD_REQUEST);
|
||||||
if (input.PageSize <= 0 || input.PageSize > 100) throw new BusinessException("每页条数必须在1-100之间", 400);
|
if (input.PageSize <= 0 || input.PageSize > 100) throw new BusinessException("每页条数必须在1-100之间", ResultCode.BAD_REQUEST);
|
||||||
|
|
||||||
RefAsync<int> totalNumber = 0;
|
RefAsync<int> totalNumber = 0;
|
||||||
var pageResult = await messageRepository.Queryable()
|
var pageResult = await messageRepository.Queryable()
|
||||||
@ -75,7 +75,7 @@ public class CommunityMessageService(BaseRepository<CommunityMessage> messageRep
|
|||||||
if (message == null)
|
if (message == null)
|
||||||
{
|
{
|
||||||
logger.LogWarning("未找到社区消息,ID: {Id}", id);
|
logger.LogWarning("未找到社区消息,ID: {Id}", id);
|
||||||
throw new BusinessException("消息不存在", 404);
|
throw new BusinessException("消息不存在", ResultCode.NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new AdminMessageDetailOutput
|
return new AdminMessageDetailOutput
|
||||||
@ -112,14 +112,14 @@ public class CommunityMessageService(BaseRepository<CommunityMessage> messageRep
|
|||||||
if (message == null)
|
if (message == null)
|
||||||
{
|
{
|
||||||
logger.LogWarning("未找到要删除的社区消息,ID: {Id}", id);
|
logger.LogWarning("未找到要删除的社区消息,ID: {Id}", id);
|
||||||
throw new BusinessException("消息不存在", 404);
|
throw new BusinessException("消息不存在", ResultCode.NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = await messageRepository.DeleteByIdAsync(id);
|
var result = await messageRepository.DeleteByIdAsync(id);
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
logger.LogError("社区消息删除失败,ID: {Id}", id);
|
logger.LogError("社区消息删除失败,ID: {Id}", id);
|
||||||
throw new BusinessException("删除消息失败", 500);
|
throw new BusinessException("删除消息失败", ResultCode.GLOBAL_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.LogInformation("社区消息删除成功,ID: {Id}", id);
|
logger.LogInformation("社区消息删除成功,ID: {Id}", id);
|
||||||
@ -134,14 +134,14 @@ public class CommunityMessageService(BaseRepository<CommunityMessage> messageRep
|
|||||||
|
|
||||||
if (status != 1 && status != 2)
|
if (status != 1 && status != 2)
|
||||||
{
|
{
|
||||||
throw new BusinessException("状态值无效,只能为1(解冻/通过)或2(冻结)", 400);
|
throw new BusinessException("状态值无效,只能为1(解冻/通过)或2(冻结)", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
var message = await messageRepository.GetByIdAsync(id);
|
var message = await messageRepository.GetByIdAsync(id);
|
||||||
if (message == null)
|
if (message == null)
|
||||||
{
|
{
|
||||||
logger.LogWarning("未找到社区消息,ID: {Id}", id);
|
logger.LogWarning("未找到社区消息,ID: {Id}", id);
|
||||||
throw new BusinessException("消息不存在", 404);
|
throw new BusinessException("消息不存在", ResultCode.NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
message.Status = status;
|
message.Status = status;
|
||||||
@ -152,7 +152,7 @@ public class CommunityMessageService(BaseRepository<CommunityMessage> messageRep
|
|||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
logger.LogError("社区消息冻结状态更新失败,ID: {Id}", id);
|
logger.LogError("社区消息冻结状态更新失败,ID: {Id}", id);
|
||||||
throw new BusinessException("更新冻结状态失败", 500);
|
throw new BusinessException("更新冻结状态失败", ResultCode.GLOBAL_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.LogInformation("社区消息冻结状态更新成功,ID: {Id}, Status: {Status}", id, status);
|
logger.LogInformation("社区消息冻结状态更新成功,ID: {Id}, Status: {Status}", id, status);
|
||||||
@ -167,14 +167,14 @@ public class CommunityMessageService(BaseRepository<CommunityMessage> messageRep
|
|||||||
|
|
||||||
if (isFeatured != 0 && isFeatured != 1)
|
if (isFeatured != 0 && isFeatured != 1)
|
||||||
{
|
{
|
||||||
throw new BusinessException("精选值无效,只能为0(取消)或1(精选)", 400);
|
throw new BusinessException("精选值无效,只能为0(取消)或1(精选)", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
var message = await messageRepository.GetByIdAsync(id);
|
var message = await messageRepository.GetByIdAsync(id);
|
||||||
if (message == null)
|
if (message == null)
|
||||||
{
|
{
|
||||||
logger.LogWarning("未找到社区消息,ID: {Id}", id);
|
logger.LogWarning("未找到社区消息,ID: {Id}", id);
|
||||||
throw new BusinessException("消息不存在", 404);
|
throw new BusinessException("消息不存在", ResultCode.NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
message.IsFeatured = isFeatured;
|
message.IsFeatured = isFeatured;
|
||||||
@ -185,7 +185,7 @@ public class CommunityMessageService(BaseRepository<CommunityMessage> messageRep
|
|||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
logger.LogError("社区消息精选设置失败,ID: {Id}", id);
|
logger.LogError("社区消息精选设置失败,ID: {Id}", id);
|
||||||
throw new BusinessException("设置精选失败", 500);
|
throw new BusinessException("设置精选失败", ResultCode.GLOBAL_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.LogInformation("社区消息精选设置成功,ID: {Id}, IsFeatured: {IsFeatured}", id, isFeatured);
|
logger.LogInformation("社区消息精选设置成功,ID: {Id}, IsFeatured: {IsFeatured}", id, isFeatured);
|
||||||
@ -202,7 +202,7 @@ public class CommunityMessageService(BaseRepository<CommunityMessage> messageRep
|
|||||||
if (message == null)
|
if (message == null)
|
||||||
{
|
{
|
||||||
logger.LogWarning("未找到社区消息,ID: {Id}", id);
|
logger.LogWarning("未找到社区消息,ID: {Id}", id);
|
||||||
throw new BusinessException("消息不存在", 404);
|
throw new BusinessException("消息不存在", ResultCode.NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
message.SortOrder = sortOrder;
|
message.SortOrder = sortOrder;
|
||||||
@ -213,7 +213,7 @@ public class CommunityMessageService(BaseRepository<CommunityMessage> messageRep
|
|||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
logger.LogError("社区消息排序权重设置失败,ID: {Id}", id);
|
logger.LogError("社区消息排序权重设置失败,ID: {Id}", id);
|
||||||
throw new BusinessException("设置排序权重失败", 500);
|
throw new BusinessException("设置排序权重失败", ResultCode.GLOBAL_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.LogInformation("社区消息排序权重设置成功,ID: {Id}, SortOrder: {SortOrder}", id, sortOrder);
|
logger.LogInformation("社区消息排序权重设置成功,ID: {Id}, SortOrder: {SortOrder}", id, sortOrder);
|
||||||
@ -228,7 +228,7 @@ public class CommunityMessageService(BaseRepository<CommunityMessage> messageRep
|
|||||||
|
|
||||||
if (ids == null || ids.Count == 0)
|
if (ids == null || ids.Count == 0)
|
||||||
{
|
{
|
||||||
throw new BusinessException("消息ID列表不能为空", 400);
|
throw new BusinessException("消息ID列表不能为空", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = await Context.Updateable<CommunityMessage>()
|
var result = await Context.Updateable<CommunityMessage>()
|
||||||
|
|||||||
@ -73,10 +73,10 @@ public class CompensationManageService(
|
|||||||
|
|
||||||
var task = await compensationTaskRepository.GetByIdAsync(taskId);
|
var task = await compensationTaskRepository.GetByIdAsync(taskId);
|
||||||
if (task == null)
|
if (task == null)
|
||||||
throw new BusinessException("补偿任务不存在", 404);
|
throw new BusinessException("补偿任务不存在", ResultCode.NOT_FOUND);
|
||||||
|
|
||||||
if (task.Status != (int)CompensationTaskStatusEnum.Failed && task.Status != (int)CompensationTaskStatusEnum.Cancelled)
|
if (task.Status != (int)CompensationTaskStatusEnum.Failed && task.Status != (int)CompensationTaskStatusEnum.Cancelled)
|
||||||
throw new BusinessException($"只有失败或已取消的任务才能重试,当前状态: {task.Status}", 400);
|
throw new BusinessException($"只有失败或已取消的任务才能重试,当前状态: {task.Status}", ResultCode.BAD_REQUEST);
|
||||||
|
|
||||||
// 重置任务状态为 Pending,清零重试次数,设置立即执行
|
// 重置任务状态为 Pending,清零重试次数,设置立即执行
|
||||||
await compensationTaskRepository.Context.Updateable<CompensationTask>()
|
await compensationTaskRepository.Context.Updateable<CompensationTask>()
|
||||||
@ -116,10 +116,10 @@ public class CompensationManageService(
|
|||||||
|
|
||||||
var task = await compensationTaskRepository.GetByIdAsync(taskId);
|
var task = await compensationTaskRepository.GetByIdAsync(taskId);
|
||||||
if (task == null)
|
if (task == null)
|
||||||
throw new BusinessException("补偿任务不存在", 404);
|
throw new BusinessException("补偿任务不存在", ResultCode.NOT_FOUND);
|
||||||
|
|
||||||
if (task.Status == (int)CompensationTaskStatusEnum.Success)
|
if (task.Status == (int)CompensationTaskStatusEnum.Success)
|
||||||
throw new BusinessException("该任务已经是成功状态,无需标记", 400);
|
throw new BusinessException("该任务已经是成功状态,无需标记", ResultCode.BAD_REQUEST);
|
||||||
|
|
||||||
// 标记为 Success
|
// 标记为 Success
|
||||||
await compensationTaskRepository.Context.Updateable<CompensationTask>()
|
await compensationTaskRepository.Context.Updateable<CompensationTask>()
|
||||||
@ -184,7 +184,7 @@ public class CompensationManageService(
|
|||||||
.FirstAsync();
|
.FirstAsync();
|
||||||
|
|
||||||
if (result == null)
|
if (result == null)
|
||||||
throw new BusinessException("补偿任务不存在", 404);
|
throw new BusinessException("补偿任务不存在", ResultCode.NOT_FOUND);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,6 +5,7 @@ using QYZH.InteractiveMagazine.Infrastructure.OSS;
|
|||||||
using QYZH.InteractiveMagazine.IService;
|
using QYZH.InteractiveMagazine.IService;
|
||||||
using QYZH.InteractiveMagazine.Models.Base;
|
using QYZH.InteractiveMagazine.Models.Base;
|
||||||
using QYZH.InteractiveMagazine.Models.Common;
|
using QYZH.InteractiveMagazine.Models.Common;
|
||||||
|
using QYZH.InteractiveMagazine.Models.Dto;
|
||||||
using QYZH.InteractiveMagazine.Models.Dto.Journal;
|
using QYZH.InteractiveMagazine.Models.Dto.Journal;
|
||||||
using QYZH.InteractiveMagazine.Models.Entity;
|
using QYZH.InteractiveMagazine.Models.Entity;
|
||||||
using QYZH.InteractiveMagazine.Models.Enum;
|
using QYZH.InteractiveMagazine.Models.Enum;
|
||||||
@ -35,10 +36,10 @@ public class JournalCatalogService : BaseRepository<JournalCatalog>, IJournalCat
|
|||||||
public async Task<long> ImportAsync(JournalImportDto input)
|
public async Task<long> ImportAsync(JournalImportDto input)
|
||||||
{
|
{
|
||||||
var Journals = await Queryable<Journal>().Where(w => w.Id == input.JournalId).FirstAsync();
|
var Journals = await Queryable<Journal>().Where(w => w.Id == input.JournalId).FirstAsync();
|
||||||
BusinessException.ThrowIf(Journals.IsNull(), "未找到书本");
|
BusinessException.ThrowIf(Journals.IsNull(), "未找到书本", ResultCode.NOT_FOUND);
|
||||||
|
|
||||||
var pageNum = await _JournalPageRepository.Queryable().Where(w => w.JournalId == input.JournalId).MaxAsync(m => m.PageNum);
|
var pageNum = await _JournalPageRepository.Queryable().Where(w => w.JournalId == input.JournalId).MaxAsync(m => m.PageNum);
|
||||||
BusinessException.ThrowIf(pageNum != 0, "已经存在书页");
|
BusinessException.ThrowIf(pageNum != 0, "已经存在书页", ResultCode.CONFLICT);
|
||||||
|
|
||||||
|
|
||||||
var JournalCatalog = new JournalCatalog()
|
var JournalCatalog = new JournalCatalog()
|
||||||
@ -106,7 +107,7 @@ public class JournalCatalogService : BaseRepository<JournalCatalog>, IJournalCat
|
|||||||
public async Task<List<JournalCatalogTreeListDto>> GetJournalCatalogListAsync(long JournalId)
|
public async Task<List<JournalCatalogTreeListDto>> GetJournalCatalogListAsync(long JournalId)
|
||||||
{
|
{
|
||||||
var Journal = await Queryable<Journal>().Where(w => w.Id == JournalId).FirstAsync();
|
var Journal = await Queryable<Journal>().Where(w => w.Id == JournalId).FirstAsync();
|
||||||
BusinessException.ThrowIf(Journal.IsNull(), "未找到书本");
|
BusinessException.ThrowIf(Journal.IsNull(), "未找到书本", ResultCode.NOT_FOUND);
|
||||||
|
|
||||||
var pageNumList = await _JournalPageRepository.Queryable()
|
var pageNumList = await _JournalPageRepository.Queryable()
|
||||||
.InnerJoin<JournalCatalog>((a, b) => a.JournalCatalogId == b.Id)
|
.InnerJoin<JournalCatalog>((a, b) => a.JournalCatalogId == b.Id)
|
||||||
@ -136,7 +137,7 @@ public class JournalCatalogService : BaseRepository<JournalCatalog>, IJournalCat
|
|||||||
public async Task<List<IcrJournalCatalogTreeDto>> GetJournalCataloTreeAsync(long JournalId)
|
public async Task<List<IcrJournalCatalogTreeDto>> GetJournalCataloTreeAsync(long JournalId)
|
||||||
{
|
{
|
||||||
var Journal = await Queryable<Journal>().Where(w => w.Id == JournalId).FirstAsync();
|
var Journal = await Queryable<Journal>().Where(w => w.Id == JournalId).FirstAsync();
|
||||||
BusinessException.ThrowIf(Journal.IsNull(), "未找到书本");
|
BusinessException.ThrowIf(Journal.IsNull(), "未找到书本", ResultCode.NOT_FOUND);
|
||||||
|
|
||||||
// 先查询所有目录
|
// 先查询所有目录
|
||||||
var allCatalogs = await base.Queryable()
|
var allCatalogs = await base.Queryable()
|
||||||
@ -276,13 +277,13 @@ public class JournalCatalogService : BaseRepository<JournalCatalog>, IJournalCat
|
|||||||
public async Task<bool> ImportCatalogAsync(long JournalId, List<JournalCatalogTreeListDto> dtos)
|
public async Task<bool> ImportCatalogAsync(long JournalId, List<JournalCatalogTreeListDto> dtos)
|
||||||
{
|
{
|
||||||
dtos = dtos.Where(c => !string.IsNullOrWhiteSpace(c.Name)).ToList();
|
dtos = dtos.Where(c => !string.IsNullOrWhiteSpace(c.Name)).ToList();
|
||||||
BusinessException.ThrowIf(dtos.Select(c => c.PageNum).Distinct().Count() != dtos.Count(), "存在重复的页码");
|
BusinessException.ThrowIf(dtos.Select(c => c.PageNum).Distinct().Count() != dtos.Count(), "存在重复的页码", ResultCode.CONFLICT);
|
||||||
|
|
||||||
var Journal = await Queryable<Journal>().Where(w => w.Id == JournalId).FirstAsync();
|
var Journal = await Queryable<Journal>().Where(w => w.Id == JournalId).FirstAsync();
|
||||||
BusinessException.ThrowIf(Journal.IsNull(), "未找到书本");
|
BusinessException.ThrowIf(Journal.IsNull(), "未找到书本", ResultCode.NOT_FOUND);
|
||||||
var pageNums = dtos.Select(c => c.PageNum).ToList();
|
var pageNums = dtos.Select(c => c.PageNum).ToList();
|
||||||
var pageNumNotExists = await _JournalPageRepository.Queryable().AnyAsync(w => w.JournalId == JournalId && !pageNums.Contains(w.PageNum));
|
var pageNumNotExists = await _JournalPageRepository.Queryable().AnyAsync(w => w.JournalId == JournalId && !pageNums.Contains(w.PageNum));
|
||||||
BusinessException.ThrowIf(pageNumNotExists, "不存在的书页");
|
BusinessException.ThrowIf(pageNumNotExists, "不存在的书页", ResultCode.NOT_FOUND);
|
||||||
|
|
||||||
var firstCatelogGroup = dtos.Select(c => c.ParentName).Distinct().Select(c => new JournalCatalog
|
var firstCatelogGroup = dtos.Select(c => c.ParentName).Distinct().Select(c => new JournalCatalog
|
||||||
{
|
{
|
||||||
@ -352,7 +353,7 @@ public class JournalCatalogService : BaseRepository<JournalCatalog>, IJournalCat
|
|||||||
if (input.Type == 1)
|
if (input.Type == 1)
|
||||||
{
|
{
|
||||||
var Journal = await Queryable<Journal>().Where(w => w.Id == input.JournalId).FirstAsync();
|
var Journal = await Queryable<Journal>().Where(w => w.Id == input.JournalId).FirstAsync();
|
||||||
BusinessException.ThrowIf(Journal.IsNull(), "未找到书本");
|
BusinessException.ThrowIf(Journal.IsNull(), "未找到书本", ResultCode.NOT_FOUND);
|
||||||
|
|
||||||
//var dotMatrixPage = new DotMatrixPage()
|
//var dotMatrixPage = new DotMatrixPage()
|
||||||
//{
|
//{
|
||||||
@ -390,10 +391,10 @@ public class JournalCatalogService : BaseRepository<JournalCatalog>, IJournalCat
|
|||||||
{
|
{
|
||||||
// 删除目录
|
// 删除目录
|
||||||
var cata = await base.Deleteable().Where(d => ids.Contains(d.Id)).ExecuteCommandAsync() > 0;
|
var cata = await base.Deleteable().Where(d => ids.Contains(d.Id)).ExecuteCommandAsync() > 0;
|
||||||
BusinessException.ThrowIf(!cata, $"删除目录失败");
|
BusinessException.ThrowIf(!cata, $"删除目录失败", ResultCode.GLOBAL_ERROR);
|
||||||
// 删除所有页/问题
|
// 删除所有页/问题
|
||||||
var pages = await _JournalPageRepository.DeleteAsync(w => ids.Contains(w.JournalCatalogId));
|
var pages = await _JournalPageRepository.DeleteAsync(w => ids.Contains(w.JournalCatalogId));
|
||||||
BusinessException.ThrowIf(pages.IsNull(), $"删除数据失败");
|
BusinessException.ThrowIf(pages.IsNull(), $"删除数据失败", ResultCode.GLOBAL_ERROR);
|
||||||
|
|
||||||
|
|
||||||
//var x = await _JournalPageRepository.DeleteAsync(w => ids.Contains(w.JournalCatalogId));
|
//var x = await _JournalPageRepository.DeleteAsync(w => ids.Contains(w.JournalCatalogId));
|
||||||
@ -406,14 +407,14 @@ public class JournalCatalogService : BaseRepository<JournalCatalog>, IJournalCat
|
|||||||
{
|
{
|
||||||
// 1. 获取源节点并校验
|
// 1. 获取源节点并校验
|
||||||
var sourceNode = await base.Queryable().Where(x => x.Id == input.SourceId).FirstAsync();
|
var sourceNode = await base.Queryable().Where(x => x.Id == input.SourceId).FirstAsync();
|
||||||
BusinessException.ThrowIf(sourceNode.IsNull(), $"要移动的节点{input.SourceId}不存在");
|
BusinessException.ThrowIf(sourceNode.IsNull(), $"要移动的节点{input.SourceId}不存在", ResultCode.NOT_FOUND);
|
||||||
|
|
||||||
|
|
||||||
// 2. 校验目标父节点(如果指定)
|
// 2. 校验目标父节点(如果指定)
|
||||||
if (input.TargetParentId > 0)
|
if (input.TargetParentId > 0)
|
||||||
{
|
{
|
||||||
var targetParentExists = await base.Queryable().Where(x => x.Id == input.TargetParentId).AnyAsync();
|
var targetParentExists = await base.Queryable().Where(x => x.Id == input.TargetParentId).AnyAsync();
|
||||||
BusinessException.ThrowIf(!targetParentExists, $"目标父节点{input.TargetParentId}不存在");
|
BusinessException.ThrowIf(!targetParentExists, $"目标父节点{input.TargetParentId}不存在", ResultCode.NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
await base.UseTranAsync(async () =>
|
await base.UseTranAsync(async () =>
|
||||||
|
|||||||
@ -9,6 +9,7 @@ using QYZH.InteractiveMagazine.Infrastructure.OSS;
|
|||||||
using QYZH.InteractiveMagazine.Infrastructure.RabbitMQ;
|
using QYZH.InteractiveMagazine.Infrastructure.RabbitMQ;
|
||||||
using QYZH.InteractiveMagazine.IService;
|
using QYZH.InteractiveMagazine.IService;
|
||||||
using QYZH.InteractiveMagazine.Models.Common;
|
using QYZH.InteractiveMagazine.Models.Common;
|
||||||
|
using QYZH.InteractiveMagazine.Models.Dto;
|
||||||
using QYZH.InteractiveMagazine.Models.Dto.Journal;
|
using QYZH.InteractiveMagazine.Models.Dto.Journal;
|
||||||
using QYZH.InteractiveMagazine.Models.Entity;
|
using QYZH.InteractiveMagazine.Models.Entity;
|
||||||
using QYZH.InteractiveMagazine.Models.Enum;
|
using QYZH.InteractiveMagazine.Models.Enum;
|
||||||
@ -34,9 +35,9 @@ public class JournalPageService(BaseRepository<Journal> JournalRepository,
|
|||||||
{
|
{
|
||||||
|
|
||||||
var Journal = await JournalRepository.Queryable().Where(w => w.Id == input.JournalId).FirstAsync();
|
var Journal = await JournalRepository.Queryable().Where(w => w.Id == input.JournalId).FirstAsync();
|
||||||
BusinessException.ThrowIf(Journal.IsNull(), "未找到书本");
|
BusinessException.ThrowIf(Journal.IsNull(), "未找到书本", ResultCode.NOT_FOUND);
|
||||||
|
|
||||||
BusinessException.ThrowIf(Journal?.Status == (int)JournalStatusEnum.Archive, "书籍已归档不能修改");
|
BusinessException.ThrowIf(Journal?.Status == (int)JournalStatusEnum.Archive, "书籍已归档不能修改", ResultCode.CONFLICT);
|
||||||
|
|
||||||
var pages = new List<JournalPage>();
|
var pages = new List<JournalPage>();
|
||||||
//var dotMatrixpages = new List<DotMatrixPage>();
|
//var dotMatrixpages = new List<DotMatrixPage>();
|
||||||
@ -65,7 +66,7 @@ public class JournalPageService(BaseRepository<Journal> JournalRepository,
|
|||||||
{
|
{
|
||||||
//using var uow = Context.Ado.BeginTran();
|
//using var uow = Context.Ado.BeginTran();
|
||||||
var pageData = await base.InsertRangeAsync(pages);
|
var pageData = await base.InsertRangeAsync(pages);
|
||||||
BusinessException.ThrowIf(pageData.IsNull(), "创建页失败");
|
BusinessException.ThrowIf(pageData.IsNull(), "创建页失败", ResultCode.GLOBAL_ERROR);
|
||||||
|
|
||||||
//var result = await dotMatrixPageRepository.InsertRangeAsync(dotMatrixpages);
|
//var result = await dotMatrixPageRepository.InsertRangeAsync(dotMatrixpages);
|
||||||
//BusinessException.ThrowIf(result, "创建点阵页失败");
|
//BusinessException.ThrowIf(result, "创建点阵页失败");
|
||||||
@ -77,12 +78,12 @@ public class JournalPageService(BaseRepository<Journal> JournalRepository,
|
|||||||
public async Task<bool> UpdateAsync(PageLayoutInput input)
|
public async Task<bool> UpdateAsync(PageLayoutInput input)
|
||||||
{
|
{
|
||||||
var page = await Queryable().Where(w => w.Id == input.Id).FirstAsync();
|
var page = await Queryable().Where(w => w.Id == input.Id).FirstAsync();
|
||||||
BusinessException.ThrowIf(page == null, "不存在此页");
|
BusinessException.ThrowIf(page == null, "不存在此页", ResultCode.NOT_FOUND);
|
||||||
|
|
||||||
var Journal = await JournalRepository.GetByIdAsync(page.JournalId);
|
var Journal = await JournalRepository.GetByIdAsync(page.JournalId);
|
||||||
BusinessException.ThrowIf(Journal == null, "不存在此书");
|
BusinessException.ThrowIf(Journal == null, "不存在此书", ResultCode.NOT_FOUND);
|
||||||
|
|
||||||
BusinessException.ThrowIf(Journal?.Status == (int)JournalStatusEnum.Archive, "书籍已归档不能修改");
|
BusinessException.ThrowIf(Journal?.Status == (int)JournalStatusEnum.Archive, "书籍已归档不能修改", ResultCode.CONFLICT);
|
||||||
var transResult = await UseTranAsync(async () =>
|
var transResult = await UseTranAsync(async () =>
|
||||||
{
|
{
|
||||||
//await dotMatrixPageRepository.Updateable().SetColumns(s => s.Area == input.Layout)
|
//await dotMatrixPageRepository.Updateable().SetColumns(s => s.Area == input.Layout)
|
||||||
@ -115,21 +116,24 @@ public class JournalPageService(BaseRepository<Journal> JournalRepository,
|
|||||||
public async Task<bool> UpdatePageNoAsync(long JournalId)
|
public async Task<bool> UpdatePageNoAsync(long JournalId)
|
||||||
{
|
{
|
||||||
var journalEntity = await JournalRepository.Queryable().FirstAsync(w => w.Id == JournalId);
|
var journalEntity = await JournalRepository.Queryable().FirstAsync(w => w.Id == JournalId);
|
||||||
BusinessException.ThrowIf(journalEntity == null, "不存在此期刊");
|
BusinessException.ThrowIf(journalEntity == null, "不存在此期刊", ResultCode.NOT_FOUND);
|
||||||
|
|
||||||
//如果书籍状态不等于“已归档”,“已废弃”,“已铺码”的情况下,就更新状态为“已铺码”
|
//如果书籍状态不等于“已归档”,“已废弃”,“已铺码”的情况下,就更新状态为“已铺码”
|
||||||
BusinessException.ThrowIf((JournalStatusEnum)journalEntity.Status is JournalStatusEnum.Abandoned or JournalStatusEnum.Archive or JournalStatusEnum.Codeing, "当前【状态】不允许铺码");
|
BusinessException.ThrowIf((JournalStatusEnum)journalEntity.Status is JournalStatusEnum.Abandoned or JournalStatusEnum.Archive or JournalStatusEnum.Codeing, "当前【状态】不允许铺码", ResultCode.UNPROCESSABLE_ENTITY);
|
||||||
|
|
||||||
var journalPageList = await JournalPageRepository.Queryable().Where(x => x.JournalId == JournalId).OrderBy(x => x.PageNum).ToListAsync();
|
var journalPageList = await JournalPageRepository.Queryable().Where(x => x.JournalId == JournalId).OrderBy(x => x.PageNum).ToListAsync();
|
||||||
BusinessException.ThrowIf(journalPageList.Count == 0, "此期刊不存在任何书页");
|
BusinessException.ThrowIf(journalPageList.Count == 0, "此期刊不存在任何书页", ResultCode.NOT_FOUND);
|
||||||
|
|
||||||
var uploadPdfUrl = DomainHelper.OssFullUrl(journalEntity?.PdfUrl!);
|
var uploadPdfKey = journalEntity?.PdfUrl?.RemoveDomain();
|
||||||
BusinessException.ThrowIf(string.IsNullOrWhiteSpace(uploadPdfUrl), "此期刊上传的PDF路径错误,请检查期刊PDF文件是否上传成功");
|
BusinessException.ThrowIf(string.IsNullOrWhiteSpace(uploadPdfKey), "此期刊上传的PDF路径错误,请检查期刊PDF文件是否上传成功", ResultCode.BAD_REQUEST);
|
||||||
|
|
||||||
|
var uploadPdfUrl = DomainHelper.OssFullUrl(uploadPdfKey);
|
||||||
|
BusinessException.ThrowIf(string.IsNullOrWhiteSpace(uploadPdfUrl), "此期刊上传的PDF路径错误,请检查期刊PDF文件是否上传成功", ResultCode.BAD_REQUEST);
|
||||||
|
|
||||||
logger.LogInformation("uploadPdfUrl:" + uploadPdfUrl);
|
logger.LogInformation("uploadPdfUrl:" + uploadPdfUrl);
|
||||||
//验证是否上传了PDF文件
|
//验证是否上传了PDF文件
|
||||||
var response = await httpClientFactory.CreateClient().SendAsync(new HttpRequestMessage(HttpMethod.Head, uploadPdfUrl));
|
var isPdfExists = ossService.DoesObjectExist(uploadPdfKey);
|
||||||
BusinessException.ThrowIf(response.StatusCode != HttpStatusCode.OK, "获取期刊上传的PDF文件失败,请检查PDF文件是否上传成功");
|
BusinessException.ThrowIf(!isPdfExists, "获取期刊上传的PDF文件失败,请检查PDF文件是否上传成功", ResultCode.GLOBAL_ERROR);
|
||||||
|
|
||||||
journalEntity.Status = (int)JournalStatusEnum.Codeing;
|
journalEntity.Status = (int)JournalStatusEnum.Codeing;
|
||||||
|
|
||||||
@ -154,14 +158,14 @@ public class JournalPageService(BaseRepository<Journal> JournalRepository,
|
|||||||
return await UseTranAsync(async () =>
|
return await UseTranAsync(async () =>
|
||||||
{
|
{
|
||||||
var journalEntity = await JournalRepository.Queryable().FirstAsync(w => w.Id == request.JournalId);
|
var journalEntity = await JournalRepository.Queryable().FirstAsync(w => w.Id == request.JournalId);
|
||||||
BusinessException.ThrowIf(journalEntity == null, "不存在此书");
|
BusinessException.ThrowIf(journalEntity == null, "不存在此书", ResultCode.NOT_FOUND);
|
||||||
|
|
||||||
//如果书籍状态不等于“铺码中”则不允许回调接口更新点阵码
|
//如果书籍状态不等于“铺码中”则不允许回调接口更新点阵码
|
||||||
BusinessException.ThrowIf(journalEntity.Status != (int)JournalStatusEnum.Codeing, "当前【状态】不允许修改铺码");
|
BusinessException.ThrowIf(journalEntity.Status != (int)JournalStatusEnum.Codeing, "当前【状态】不允许修改铺码", ResultCode.UNPROCESSABLE_ENTITY);
|
||||||
|
|
||||||
var bookPageList = await JournalPageRepository.Queryable().Where(x => x.JournalId == request.JournalId).OrderBy(x => x.PageNum).ToListAsync();
|
var bookPageList = await JournalPageRepository.Queryable().Where(x => x.JournalId == request.JournalId).OrderBy(x => x.PageNum).ToListAsync();
|
||||||
|
|
||||||
BusinessException.ThrowIf(bookPageList.Count == 0, "此书不存在任何书页");
|
BusinessException.ThrowIf(bookPageList.Count == 0, "此书不存在任何书页", ResultCode.NOT_FOUND);
|
||||||
|
|
||||||
journalEntity.Status = (int)request.Status!.Value;
|
journalEntity.Status = (int)request.Status!.Value;
|
||||||
journalEntity.UpdatedAt = DateTime.Now;
|
journalEntity.UpdatedAt = DateTime.Now;
|
||||||
@ -177,7 +181,7 @@ public class JournalPageService(BaseRepository<Journal> JournalRepository,
|
|||||||
{
|
{
|
||||||
journalEntity.DownloadJournalPagePdfName = request.DownloadJournalPagePdfName;
|
journalEntity.DownloadJournalPagePdfName = request.DownloadJournalPagePdfName;
|
||||||
|
|
||||||
BusinessException.ThrowIf(request.PageNo.Length != bookPageList.Count, $"点阵码条数与页码数量不匹配,点阵码条数:{request.PageNo.Length},页码数量:{bookPageList.Count}");
|
BusinessException.ThrowIf(request.PageNo.Length != bookPageList.Count, $"点阵码条数与页码数量不匹配,点阵码条数:{request.PageNo.Length},页码数量:{bookPageList.Count}", ResultCode.BAD_REQUEST);
|
||||||
|
|
||||||
|
|
||||||
for (var i = 0; i < bookPageList.Count; i++)
|
for (var i = 0; i < bookPageList.Count; i++)
|
||||||
|
|||||||
@ -3,6 +3,7 @@ using QYZH.InteractiveMagazine.Common.Extensions;
|
|||||||
using QYZH.InteractiveMagazine.Infrastructure.OSS;
|
using QYZH.InteractiveMagazine.Infrastructure.OSS;
|
||||||
using QYZH.InteractiveMagazine.IService;
|
using QYZH.InteractiveMagazine.IService;
|
||||||
using QYZH.InteractiveMagazine.Models.Common;
|
using QYZH.InteractiveMagazine.Models.Common;
|
||||||
|
using QYZH.InteractiveMagazine.Models.Dto;
|
||||||
using QYZH.InteractiveMagazine.Models.Dto.Journal;
|
using QYZH.InteractiveMagazine.Models.Dto.Journal;
|
||||||
using QYZH.InteractiveMagazine.Models.Entity;
|
using QYZH.InteractiveMagazine.Models.Entity;
|
||||||
using QYZH.InteractiveMagazine.Models.Enum;
|
using QYZH.InteractiveMagazine.Models.Enum;
|
||||||
@ -18,7 +19,7 @@ public class JournalPageTaskService(BaseRepository<Journal> journalRepository, O
|
|||||||
public async Task<long?> InsertAsync(JournalPageTaskAddInput input)
|
public async Task<long?> InsertAsync(JournalPageTaskAddInput input)
|
||||||
{
|
{
|
||||||
var JournalStatus = await journalRepository.Queryable().Where(w => w.Id == input.JournalId).Select(s => s.Status).FirstAsync();
|
var JournalStatus = await journalRepository.Queryable().Where(w => w.Id == input.JournalId).Select(s => s.Status).FirstAsync();
|
||||||
BusinessException.ThrowIf(JournalStatus == (int)JournalStatusEnum.Archive, "书籍已归档不能添加题目");
|
BusinessException.ThrowIf(JournalStatus == (int)JournalStatusEnum.Archive, "书籍已归档不能添加题目", ResultCode.CONFLICT);
|
||||||
|
|
||||||
var map = input.Adapt<JournalPageTask>();
|
var map = input.Adapt<JournalPageTask>();
|
||||||
map.Id = YitIdHelper.NextId();
|
map.Id = YitIdHelper.NextId();
|
||||||
@ -28,7 +29,7 @@ public class JournalPageTaskService(BaseRepository<Journal> journalRepository, O
|
|||||||
{
|
{
|
||||||
var startNo = $"{no[0]}-{no[1]}-{no[2]}-1";
|
var startNo = $"{no[0]}-{no[1]}-{no[2]}-1";
|
||||||
var groupTask = await Queryable().Where(w => w.No == startNo && w.JournalId == input.JournalId).FirstAsync();
|
var groupTask = await Queryable().Where(w => w.No == startNo && w.JournalId == input.JournalId).FirstAsync();
|
||||||
BusinessException.ThrowIf(groupTask.IsNull(), "未找到关联跨页的第一部分");
|
BusinessException.ThrowIf(groupTask.IsNull(), "未找到关联跨页的第一部分", ResultCode.NOT_FOUND);
|
||||||
map.GroupId = groupTask.GroupId;
|
map.GroupId = groupTask.GroupId;
|
||||||
map.Type = groupTask.Type;
|
map.Type = groupTask.Type;
|
||||||
}
|
}
|
||||||
@ -42,13 +43,13 @@ public class JournalPageTaskService(BaseRepository<Journal> journalRepository, O
|
|||||||
public async Task<bool> UpdateAsync(JournalPageTaskUpdateInput input)
|
public async Task<bool> UpdateAsync(JournalPageTaskUpdateInput input)
|
||||||
{
|
{
|
||||||
var JournalStatus = await journalRepository.Queryable().Where(w => w.Id == input.JournalId).Select(s => s.Status).FirstAsync();
|
var JournalStatus = await journalRepository.Queryable().Where(w => w.Id == input.JournalId).Select(s => s.Status).FirstAsync();
|
||||||
BusinessException.ThrowIf(JournalStatus == (int)JournalStatusEnum.Archive, "书籍已归档不能修改题目");
|
BusinessException.ThrowIf(JournalStatus == (int)JournalStatusEnum.Archive, "书籍已归档不能修改题目", ResultCode.CONFLICT);
|
||||||
|
|
||||||
var task = await base.Queryable().Where(w => w.Id == input.Id).FirstAsync();
|
var task = await base.Queryable().Where(w => w.Id == input.Id).FirstAsync();
|
||||||
BusinessException.ThrowIf(task.IsNull(), "未找到关联的题号");
|
BusinessException.ThrowIf(task.IsNull(), "未找到关联的题号", ResultCode.NOT_FOUND);
|
||||||
|
|
||||||
var sameTask = await base.Queryable().Where(w => w.No == input.No && w.JournalId == input.JournalId && w.Id != input.Id).FirstAsync();
|
var sameTask = await base.Queryable().Where(w => w.No == input.No && w.JournalId == input.JournalId && w.Id != input.Id).FirstAsync();
|
||||||
BusinessException.ThrowIf(sameTask.IsNotEmpty(), "已经存在相同题号题目");
|
BusinessException.ThrowIf(sameTask.IsNotEmpty(), "已经存在相同题号题目", ResultCode.CONFLICT);
|
||||||
|
|
||||||
|
|
||||||
var key = $"journal/{task.JournalId}/{task.JournalPageId}/{task.GroupId}";
|
var key = $"journal/{task.JournalId}/{task.JournalPageId}/{task.GroupId}";
|
||||||
@ -74,7 +75,7 @@ public class JournalPageTaskService(BaseRepository<Journal> journalRepository, O
|
|||||||
{
|
{
|
||||||
var startNo = $"{no[0]}-{no[1]}-{no[2]}-1";
|
var startNo = $"{no[0]}-{no[1]}-{no[2]}-1";
|
||||||
var groupTask = await Queryable().Where(w => w.No == startNo && w.JournalId == input.JournalId).FirstAsync();
|
var groupTask = await Queryable().Where(w => w.No == startNo && w.JournalId == input.JournalId).FirstAsync();
|
||||||
BusinessException.ThrowIf(groupTask.IsNull(), "未找到关联跨页的第一部分");
|
BusinessException.ThrowIf(groupTask.IsNull(), "未找到关联跨页的第一部分", ResultCode.NOT_FOUND);
|
||||||
task.GroupId = groupTask.GroupId;
|
task.GroupId = groupTask.GroupId;
|
||||||
task.Type = groupTask.Type;
|
task.Type = groupTask.Type;
|
||||||
}
|
}
|
||||||
@ -124,7 +125,7 @@ public class JournalPageTaskService(BaseRepository<Journal> journalRepository, O
|
|||||||
public async Task<bool> DeleteAsync(long id)
|
public async Task<bool> DeleteAsync(long id)
|
||||||
{
|
{
|
||||||
var task = await base.Queryable().Where(w => w.Id == id).FirstAsync();
|
var task = await base.Queryable().Where(w => w.Id == id).FirstAsync();
|
||||||
BusinessException.ThrowIf(task.IsNull(), "问题不存在");
|
BusinessException.ThrowIf(task.IsNull(), "问题不存在", ResultCode.NOT_FOUND);
|
||||||
|
|
||||||
var key = $"journal/{task.JournalId}/{task.JournalPageId}/{id}";
|
var key = $"journal/{task.JournalId}/{task.JournalPageId}/{id}";
|
||||||
|
|
||||||
@ -139,7 +140,7 @@ public class JournalPageTaskService(BaseRepository<Journal> journalRepository, O
|
|||||||
public async Task<bool> ComplementAsync(JournalPageTaskComplementInput input)
|
public async Task<bool> ComplementAsync(JournalPageTaskComplementInput input)
|
||||||
{
|
{
|
||||||
var task = await base.Queryable().Where(w => w.Id == input.Id).FirstAsync();
|
var task = await base.Queryable().Where(w => w.Id == input.Id).FirstAsync();
|
||||||
BusinessException.ThrowIf(task.IsNull(), "问题不存在");
|
BusinessException.ThrowIf(task.IsNull(), "问题不存在", ResultCode.NOT_FOUND);
|
||||||
|
|
||||||
if (input.AudioUrl.NotNull())
|
if (input.AudioUrl.NotNull())
|
||||||
{
|
{
|
||||||
@ -159,7 +160,7 @@ public class JournalPageTaskService(BaseRepository<Journal> journalRepository, O
|
|||||||
public async Task<long> AddAnswerAsync(JournalTaskAnswerAddInput input)
|
public async Task<long> AddAnswerAsync(JournalTaskAnswerAddInput input)
|
||||||
{
|
{
|
||||||
var task = await base.Queryable().Where(w => w.Id == input.JournalPageTaskId).FirstAsync();
|
var task = await base.Queryable().Where(w => w.Id == input.JournalPageTaskId).FirstAsync();
|
||||||
BusinessException.ThrowIf(task.IsNull(), "问题不存在");
|
BusinessException.ThrowIf(task.IsNull(), "问题不存在", ResultCode.NOT_FOUND);
|
||||||
|
|
||||||
var key = $"journal/{task.JournalId}/{task.JournalPageId}/{task.GroupId}";
|
var key = $"journal/{task.JournalId}/{task.JournalPageId}/{task.GroupId}";
|
||||||
input.Answer = Deal(null, input.Answer, key, "answer");
|
input.Answer = Deal(null, input.Answer, key, "answer");
|
||||||
@ -181,7 +182,7 @@ public class JournalPageTaskService(BaseRepository<Journal> journalRepository, O
|
|||||||
public async Task<bool> UpdateAnswerAsync(JournalTaskAnswerUpdateInput input)
|
public async Task<bool> UpdateAnswerAsync(JournalTaskAnswerUpdateInput input)
|
||||||
{
|
{
|
||||||
var answer = await answerRepository.Queryable().Where(a => a.Id == input.Id).FirstAsync();
|
var answer = await answerRepository.Queryable().Where(a => a.Id == input.Id).FirstAsync();
|
||||||
BusinessException.ThrowIf(answer.IsNull(), "答案不存在");
|
BusinessException.ThrowIf(answer.IsNull(), "答案不存在", ResultCode.NOT_FOUND);
|
||||||
|
|
||||||
var task = await base.Queryable().Where(w => w.Id == answer.JournalPageTaskId).FirstAsync();
|
var task = await base.Queryable().Where(w => w.Id == answer.JournalPageTaskId).FirstAsync();
|
||||||
var key = $"journal/{task.JournalId}/{task.JournalPageId}/{task.GroupId}";
|
var key = $"journal/{task.JournalId}/{task.JournalPageId}/{task.GroupId}";
|
||||||
@ -199,7 +200,7 @@ public class JournalPageTaskService(BaseRepository<Journal> journalRepository, O
|
|||||||
public async Task<bool> DeleteAnswerAsync(long id)
|
public async Task<bool> DeleteAnswerAsync(long id)
|
||||||
{
|
{
|
||||||
var answer = await answerRepository.Queryable().Where(a => a.Id == id).FirstAsync();
|
var answer = await answerRepository.Queryable().Where(a => a.Id == id).FirstAsync();
|
||||||
BusinessException.ThrowIf(answer.IsNull(), "答案不存在");
|
BusinessException.ThrowIf(answer.IsNull(), "答案不存在", ResultCode.NOT_FOUND);
|
||||||
|
|
||||||
var task = await base.Queryable().Where(w => w.Id == answer.JournalPageTaskId).FirstAsync();
|
var task = await base.Queryable().Where(w => w.Id == answer.JournalPageTaskId).FirstAsync();
|
||||||
var key = $"journal/{task.JournalId}/{task.JournalPageId}/{task.GroupId}";
|
var key = $"journal/{task.JournalId}/{task.JournalPageId}/{task.GroupId}";
|
||||||
|
|||||||
@ -68,7 +68,7 @@ public class JournalService(BaseRepository<JournalPage> JournalPageRepository,
|
|||||||
/// <returns>新杂志ID</returns>
|
/// <returns>新杂志ID</returns>
|
||||||
public async Task<BaseResponse<long>> AddAsync(JournalAddDto input)
|
public async Task<BaseResponse<long>> AddAsync(JournalAddDto input)
|
||||||
{
|
{
|
||||||
BusinessException.ThrowIf(string.IsNullOrWhiteSpace(input.Name), "书籍名称不能为空");
|
BusinessException.ThrowIf(string.IsNullOrWhiteSpace(input.Name), "书籍名称不能为空", ResultCode.BAD_REQUEST);
|
||||||
|
|
||||||
var journal = new Journal
|
var journal = new Journal
|
||||||
{
|
{
|
||||||
@ -114,7 +114,7 @@ public class JournalService(BaseRepository<JournalPage> JournalPageRepository,
|
|||||||
var res = await base.InsertAsync(journal);
|
var res = await base.InsertAsync(journal);
|
||||||
if (!res)
|
if (!res)
|
||||||
{
|
{
|
||||||
new BusinessException("创建失败");
|
new BusinessException("创建失败", ResultCode.GLOBAL_ERROR);
|
||||||
}
|
}
|
||||||
logger.LogInformation("杂志创建成功,ID: {Id}, 名称: {Name}", journal.Id, input.Name);
|
logger.LogInformation("杂志创建成功,ID: {Id}, 名称: {Name}", journal.Id, input.Name);
|
||||||
return BaseResponse<long>.Success(journal.Id);
|
return BaseResponse<long>.Success(journal.Id);
|
||||||
@ -129,8 +129,8 @@ public class JournalService(BaseRepository<JournalPage> JournalPageRepository,
|
|||||||
{
|
{
|
||||||
|
|
||||||
var Journal = await base.GetByIdAsync(input.Id);
|
var Journal = await base.GetByIdAsync(input.Id);
|
||||||
BusinessException.ThrowIf(Journal.IsNull(), "不存在的Id");
|
BusinessException.ThrowIf(Journal.IsNull(), "不存在的Id", ResultCode.NOT_FOUND);
|
||||||
BusinessException.ThrowIf(Journal.Status == (int)JournalStatusEnum.Archive, "已归档不可编辑");
|
BusinessException.ThrowIf(Journal.Status == (int)JournalStatusEnum.Archive, "已归档不可编辑", ResultCode.CONFLICT);
|
||||||
if (string.IsNullOrWhiteSpace(input.Cover))
|
if (string.IsNullOrWhiteSpace(input.Cover))
|
||||||
{
|
{
|
||||||
Journal.Cover = null;
|
Journal.Cover = null;
|
||||||
@ -204,8 +204,8 @@ public class JournalService(BaseRepository<JournalPage> JournalPageRepository,
|
|||||||
|
|
||||||
public async Task<bool> DeleteAsync(List<long> ids)
|
public async Task<bool> DeleteAsync(List<long> ids)
|
||||||
{
|
{
|
||||||
BusinessException.ThrowIf(!base.Queryable().Any(w => ids.Contains(w.Id)), "ID不存在");
|
BusinessException.ThrowIf(!base.Queryable().Any(w => ids.Contains(w.Id)), "ID不存在", ResultCode.NOT_FOUND);
|
||||||
BusinessException.ThrowIf(base.Queryable().Any(w => ids.Contains(w.Id) && w.Status == (int)JournalStatusEnum.Archive), "已归档不可删除");
|
BusinessException.ThrowIf(base.Queryable().Any(w => ids.Contains(w.Id) && w.Status == (int)JournalStatusEnum.Archive), "已归档不可删除", ResultCode.CONFLICT);
|
||||||
var result = await UseTranAsync(async () =>
|
var result = await UseTranAsync(async () =>
|
||||||
{
|
{
|
||||||
await base.DeleteAsync(d => ids.Contains(d.Id));
|
await base.DeleteAsync(d => ids.Contains(d.Id));
|
||||||
@ -282,11 +282,11 @@ public class JournalService(BaseRepository<JournalPage> JournalPageRepository,
|
|||||||
public async Task<DotMatrixOutput> PrintCodeAsync(long id)
|
public async Task<DotMatrixOutput> PrintCodeAsync(long id)
|
||||||
{
|
{
|
||||||
var Journal = await base.Queryable().Where(w => w.Id == id).FirstAsync();
|
var Journal = await base.Queryable().Where(w => w.Id == id).FirstAsync();
|
||||||
BusinessException.ThrowIf(Journal.IsNull(), "不存在书");
|
BusinessException.ThrowIf(Journal.IsNull(), "不存在书", ResultCode.NOT_FOUND);
|
||||||
BusinessException.ThrowIf(Journal.Status == (int)JournalStatusEnum.Codeing, "正在生成中...");
|
BusinessException.ThrowIf(Journal.Status == (int)JournalStatusEnum.Codeing, "正在生成中...", ResultCode.CONFLICT);
|
||||||
|
|
||||||
var pages = await JournalPageRepository.Queryable().Where(w => w.JournalId == id).ToListAsync();
|
var pages = await JournalPageRepository.Queryable().Where(w => w.JournalId == id).ToListAsync();
|
||||||
BusinessException.ThrowIf(pages.IsNull(), "不存在页");
|
BusinessException.ThrowIf(pages.IsNull(), "不存在页", ResultCode.NOT_FOUND);
|
||||||
|
|
||||||
var output = new DotMatrixOutput()
|
var output = new DotMatrixOutput()
|
||||||
{
|
{
|
||||||
@ -315,8 +315,8 @@ public class JournalService(BaseRepository<JournalPage> JournalPageRepository,
|
|||||||
{
|
{
|
||||||
var book = await base.GetByIdAsync(id);
|
var book = await base.GetByIdAsync(id);
|
||||||
var tasks = await Context.Queryable<JournalPageTask>().Where(w => w.JournalId == id).ToListAsync();
|
var tasks = await Context.Queryable<JournalPageTask>().Where(w => w.JournalId == id).ToListAsync();
|
||||||
BusinessException.ThrowIf(tasks.Count == 0 && status == JournalStatusEnum.Archive, "未添加任何题目,无法归档");
|
BusinessException.ThrowIf(tasks.Count == 0 && status == JournalStatusEnum.Archive, "未添加任何题目,无法归档", ResultCode.UNPROCESSABLE_ENTITY);
|
||||||
BusinessException.ThrowIf(tasks.Any(a => string.IsNullOrWhiteSpace(a.TaskUrl)) && status == JournalStatusEnum.Archive, $"{string.Join(',', tasks.Where(a => string.IsNullOrWhiteSpace(a.TaskUrl)).Select(a => a.No).ToList())}未保存,无法归档");
|
BusinessException.ThrowIf(tasks.Any(a => string.IsNullOrWhiteSpace(a.TaskUrl)) && status == JournalStatusEnum.Archive, $"{string.Join(',', tasks.Where(a => string.IsNullOrWhiteSpace(a.TaskUrl)).Select(a => a.No).ToList())}未保存,无法归档", ResultCode.UNPROCESSABLE_ENTITY);
|
||||||
var res = await base.Updateable().SetColumns(s => s.Status, status).Where(w => w.Id == id).ExecuteCommandAsync() > 0;
|
var res = await base.Updateable().SetColumns(s => s.Status, status).Where(w => w.Id == id).ExecuteCommandAsync() > 0;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,12 +27,12 @@ public class MedalService(BaseRepository<Medal> medalRepository, IOptions<MedalR
|
|||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(input.Name))
|
if (string.IsNullOrWhiteSpace(input.Name))
|
||||||
{
|
{
|
||||||
throw new BusinessException("勋章名称不能为空", 400);
|
throw new BusinessException("勋章名称不能为空", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(input.Type))
|
if (string.IsNullOrWhiteSpace(input.Type))
|
||||||
{
|
{
|
||||||
throw new BusinessException("勋章类型不能为空", 400);
|
throw new BusinessException("勋章类型不能为空", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
var medal = new Medal
|
var medal = new Medal
|
||||||
@ -58,7 +58,7 @@ public class MedalService(BaseRepository<Medal> medalRepository, IOptions<MedalR
|
|||||||
var result = await medalRepository.InsertAsync(medal);
|
var result = await medalRepository.InsertAsync(medal);
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
throw new BusinessException("创建勋章失败", 500);
|
throw new BusinessException("创建勋章失败", ResultCode.GLOBAL_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input.Rules != null && input.Rules.Count > 0)
|
if (input.Rules != null && input.Rules.Count > 0)
|
||||||
@ -74,7 +74,7 @@ public class MedalService(BaseRepository<Medal> medalRepository, IOptions<MedalR
|
|||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.LogError(ex, "勋章创建事务失败,勋章名称: {Name}", input.Name);
|
logger.LogError(ex, "勋章创建事务失败,勋章名称: {Name}", input.Name);
|
||||||
throw new BusinessException("创建勋章失败", 500);
|
throw new BusinessException("创建勋章失败", ResultCode.GLOBAL_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.LogInformation("勋章创建成功,勋章名称: {Name}, ID: {Id}", input.Name, medal.Id);
|
logger.LogInformation("勋章创建成功,勋章名称: {Name}, ID: {Id}", input.Name, medal.Id);
|
||||||
@ -94,17 +94,17 @@ public class MedalService(BaseRepository<Medal> medalRepository, IOptions<MedalR
|
|||||||
if (medal == null)
|
if (medal == null)
|
||||||
{
|
{
|
||||||
logger.LogWarning("未找到要更新的勋章,ID: {Id}", id);
|
logger.LogWarning("未找到要更新的勋章,ID: {Id}", id);
|
||||||
throw new BusinessException("勋章不存在", 404);
|
throw new BusinessException("勋章不存在", ResultCode.NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(input.Name))
|
if (string.IsNullOrWhiteSpace(input.Name))
|
||||||
{
|
{
|
||||||
throw new BusinessException("勋章名称不能为空", 400);
|
throw new BusinessException("勋章名称不能为空", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(input.Type))
|
if (string.IsNullOrWhiteSpace(input.Type))
|
||||||
{
|
{
|
||||||
throw new BusinessException("勋章类型不能为空", 400);
|
throw new BusinessException("勋章类型不能为空", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
medal.Name = input.Name.Trim();
|
medal.Name = input.Name.Trim();
|
||||||
@ -123,7 +123,7 @@ public class MedalService(BaseRepository<Medal> medalRepository, IOptions<MedalR
|
|||||||
var result = await medalRepository.UpdateAsync(medal);
|
var result = await medalRepository.UpdateAsync(medal);
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
throw new BusinessException("更新勋章失败", 500);
|
throw new BusinessException("更新勋章失败", ResultCode.GLOBAL_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除旧规则,重新插入新规则
|
// 删除旧规则,重新插入新规则
|
||||||
@ -145,7 +145,7 @@ public class MedalService(BaseRepository<Medal> medalRepository, IOptions<MedalR
|
|||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.LogError(ex, "勋章更新事务失败,ID: {Id}", id);
|
logger.LogError(ex, "勋章更新事务失败,ID: {Id}", id);
|
||||||
throw new BusinessException("更新勋章失败", 500);
|
throw new BusinessException("更新勋章失败", ResultCode.GLOBAL_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.LogInformation("勋章更新成功,ID: {Id}", id);
|
logger.LogInformation("勋章更新成功,ID: {Id}", id);
|
||||||
@ -165,7 +165,7 @@ public class MedalService(BaseRepository<Medal> medalRepository, IOptions<MedalR
|
|||||||
if (medal == null)
|
if (medal == null)
|
||||||
{
|
{
|
||||||
logger.LogWarning("未找到要删除的勋章,ID: {Id}", id);
|
logger.LogWarning("未找到要删除的勋章,ID: {Id}", id);
|
||||||
throw new BusinessException("勋章不存在", 404);
|
throw new BusinessException("勋章不存在", ResultCode.NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
@ -175,7 +175,7 @@ public class MedalService(BaseRepository<Medal> medalRepository, IOptions<MedalR
|
|||||||
var result = await medalRepository.DeleteByIdAsync(id);
|
var result = await medalRepository.DeleteByIdAsync(id);
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
throw new BusinessException("删除勋章失败", 500);
|
throw new BusinessException("删除勋章失败", ResultCode.GLOBAL_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 同时软删除关联规则
|
// 同时软删除关联规则
|
||||||
@ -192,7 +192,7 @@ public class MedalService(BaseRepository<Medal> medalRepository, IOptions<MedalR
|
|||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.LogError(ex, "勋章删除事务失败,ID: {Id}", id);
|
logger.LogError(ex, "勋章删除事务失败,ID: {Id}", id);
|
||||||
throw new BusinessException("删除勋章失败", 500);
|
throw new BusinessException("删除勋章失败", ResultCode.GLOBAL_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.LogInformation("勋章删除成功,ID: {Id}", id);
|
logger.LogInformation("勋章删除成功,ID: {Id}", id);
|
||||||
@ -209,7 +209,7 @@ public class MedalService(BaseRepository<Medal> medalRepository, IOptions<MedalR
|
|||||||
if (medal == null)
|
if (medal == null)
|
||||||
{
|
{
|
||||||
logger.LogWarning("未找到勋章,ID: {Id}", id);
|
logger.LogWarning("未找到勋章,ID: {Id}", id);
|
||||||
throw new BusinessException("勋章不存在", 404);
|
throw new BusinessException("勋章不存在", ResultCode.NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
var rules = await GetRulesByMedalIdAsync(medal.Id);
|
var rules = await GetRulesByMedalIdAsync(medal.Id);
|
||||||
@ -225,12 +225,12 @@ public class MedalService(BaseRepository<Medal> medalRepository, IOptions<MedalR
|
|||||||
|
|
||||||
if (input.PageIndex <= 0)
|
if (input.PageIndex <= 0)
|
||||||
{
|
{
|
||||||
throw new BusinessException("页码必须大于0", 400);
|
throw new BusinessException("页码必须大于0", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input.PageSize <= 0 || input.PageSize > 100)
|
if (input.PageSize <= 0 || input.PageSize > 100)
|
||||||
{
|
{
|
||||||
throw new BusinessException("每页条数必须在1-100之间", 400);
|
throw new BusinessException("每页条数必须在1-100之间", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
RefAsync<int> totalNumber = 0;
|
RefAsync<int> totalNumber = 0;
|
||||||
@ -266,7 +266,7 @@ public class MedalService(BaseRepository<Medal> medalRepository, IOptions<MedalR
|
|||||||
if (medal == null)
|
if (medal == null)
|
||||||
{
|
{
|
||||||
logger.LogWarning("未找到要更新状态的勋章,ID: {Id}", id);
|
logger.LogWarning("未找到要更新状态的勋章,ID: {Id}", id);
|
||||||
throw new BusinessException("勋章不存在", 404);
|
throw new BusinessException("勋章不存在", ResultCode.NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
medal.Status = medal.Status == 0 ? 1 : 0;
|
medal.Status = medal.Status == 0 ? 1 : 0;
|
||||||
@ -277,7 +277,7 @@ public class MedalService(BaseRepository<Medal> medalRepository, IOptions<MedalR
|
|||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
logger.LogError("勋章状态更新失败,ID: {Id}", id);
|
logger.LogError("勋章状态更新失败,ID: {Id}", id);
|
||||||
throw new BusinessException("更新勋章状态失败", 500);
|
throw new BusinessException("更新勋章状态失败", ResultCode.GLOBAL_ERROR);
|
||||||
}
|
}
|
||||||
logger.LogInformation("勋章状态更新成功,ID: {Id}, Status: {Status}", id, medal.Status);
|
logger.LogInformation("勋章状态更新成功,ID: {Id}, Status: {Status}", id, medal.Status);
|
||||||
return result;
|
return result;
|
||||||
@ -364,19 +364,19 @@ public class MedalService(BaseRepository<Medal> medalRepository, IOptions<MedalR
|
|||||||
|
|
||||||
if (input.MedalId <= 0)
|
if (input.MedalId <= 0)
|
||||||
{
|
{
|
||||||
throw new BusinessException("勋章ID无效", 400);
|
throw new BusinessException("勋章ID无效", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
var medal = await medalRepository.GetByIdAsync(input.MedalId);
|
var medal = await medalRepository.GetByIdAsync(input.MedalId);
|
||||||
if (medal == null)
|
if (medal == null)
|
||||||
{
|
{
|
||||||
logger.LogWarning("未找到要激活的勋章,勋章ID: {MedalId}", input.MedalId);
|
logger.LogWarning("未找到要激活的勋章,勋章ID: {MedalId}", input.MedalId);
|
||||||
throw new BusinessException("勋章不存在", 404);
|
throw new BusinessException("勋章不存在", ResultCode.NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (medal.Status != 1)
|
if (medal.Status != 1)
|
||||||
{
|
{
|
||||||
throw new BusinessException("该勋章当前不可获得", 400);
|
throw new BusinessException("该勋章当前不可获得", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 规则校验
|
// 规则校验
|
||||||
@ -384,7 +384,7 @@ public class MedalService(BaseRepository<Medal> medalRepository, IOptions<MedalR
|
|||||||
if (!passed)
|
if (!passed)
|
||||||
{
|
{
|
||||||
logger.LogWarning("勋章规则校验未通过,用户ID: {UserId}, 勋章ID: {MedalId}, 原因: {Reason}", userId, input.MedalId, failReason);
|
logger.LogWarning("勋章规则校验未通过,用户ID: {UserId}, 勋章ID: {MedalId}, 原因: {Reason}", userId, input.MedalId, failReason);
|
||||||
throw new BusinessException(failReason!, 400);
|
throw new BusinessException(failReason!, ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
var existingUserMedal = await Context.Queryable<UserMedal>()
|
var existingUserMedal = await Context.Queryable<UserMedal>()
|
||||||
@ -393,7 +393,7 @@ public class MedalService(BaseRepository<Medal> medalRepository, IOptions<MedalR
|
|||||||
|
|
||||||
if (existingUserMedal != null)
|
if (existingUserMedal != null)
|
||||||
{
|
{
|
||||||
throw new BusinessException("您已拥有该勋章", 400);
|
throw new BusinessException("您已拥有该勋章", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
var userMedal = new UserMedal
|
var userMedal = new UserMedal
|
||||||
@ -414,7 +414,7 @@ public class MedalService(BaseRepository<Medal> medalRepository, IOptions<MedalR
|
|||||||
if (insertResult <= 0)
|
if (insertResult <= 0)
|
||||||
{
|
{
|
||||||
logger.LogError("勋章激活失败,用户ID: {UserId}, 勋章ID: {MedalId}", userId, input.MedalId);
|
logger.LogError("勋章激活失败,用户ID: {UserId}, 勋章ID: {MedalId}", userId, input.MedalId);
|
||||||
throw new BusinessException("激活勋章失败", 500);
|
throw new BusinessException("激活勋章失败", ResultCode.GLOBAL_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.LogInformation("勋章激活成功,用户ID: {UserId}, 勋章ID: {MedalId}", userId, input.MedalId);
|
logger.LogInformation("勋章激活成功,用户ID: {UserId}, 勋章ID: {MedalId}", userId, input.MedalId);
|
||||||
@ -486,7 +486,7 @@ public class MedalService(BaseRepository<Medal> medalRepository, IOptions<MedalR
|
|||||||
if (count <= 0)
|
if (count <= 0)
|
||||||
{
|
{
|
||||||
logger.LogError("勋章规则插入失败,MedalId: {MedalId}", medalId);
|
logger.LogError("勋章规则插入失败,MedalId: {MedalId}", medalId);
|
||||||
throw new BusinessException("创建勋章规则失败", 500);
|
throw new BusinessException("创建勋章规则失败", ResultCode.GLOBAL_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.LogInformation("勋章规则创建成功,MedalId: {MedalId}, 规则数: {Count}", medalId, rules.Count);
|
logger.LogInformation("勋章规则创建成功,MedalId: {MedalId}, 规则数: {Count}", medalId, rules.Count);
|
||||||
|
|||||||
@ -105,7 +105,7 @@ public class OperationLogService(
|
|||||||
|
|
||||||
if (log == null)
|
if (log == null)
|
||||||
{
|
{
|
||||||
throw new BusinessException("操作日志记录不存在");
|
throw new BusinessException("操作日志记录不存在", ResultCode.NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = new OperationLogDetailOutput
|
var result = new OperationLogDetailOutput
|
||||||
|
|||||||
@ -223,12 +223,12 @@ public class PetService(
|
|||||||
|
|
||||||
if (input.PetId <= 0)
|
if (input.PetId <= 0)
|
||||||
{
|
{
|
||||||
throw new BusinessException("宠物Id不能为空", 400);
|
throw new BusinessException("宠物Id不能为空", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input.GrowthPoints <= 0)
|
if (input.GrowthPoints <= 0)
|
||||||
{
|
{
|
||||||
throw new BusinessException("成长值必须大于0", 400);
|
throw new BusinessException("成长值必须大于0", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查询宠物
|
// 查询宠物
|
||||||
@ -236,21 +236,21 @@ public class PetService(
|
|||||||
if (pet == null || pet.IsDeleted)
|
if (pet == null || pet.IsDeleted)
|
||||||
{
|
{
|
||||||
logger.LogWarning("喂养失败,宠物不存在,PetId: {PetId}", input.PetId);
|
logger.LogWarning("喂养失败,宠物不存在,PetId: {PetId}", input.PetId);
|
||||||
throw new BusinessException("宠物不存在", 404);
|
throw new BusinessException("宠物不存在", ResultCode.NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 校验宠物归属
|
// 校验宠物归属
|
||||||
if (pet.UserId != userId)
|
if (pet.UserId != userId)
|
||||||
{
|
{
|
||||||
logger.LogWarning("喂养失败,无权操作该宠物,UserId: {UserId}, PetUserId: {PetUserId}", userId, pet.UserId);
|
logger.LogWarning("喂养失败,无权操作该宠物,UserId: {UserId}, PetUserId: {PetUserId}", userId, pet.UserId);
|
||||||
throw new BusinessException("无权操作该宠物", 403);
|
throw new BusinessException("无权操作该宠物", ResultCode.FORBIDDEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 校验宠物状态
|
// 校验宠物状态
|
||||||
if (pet.Status != (int)UserPetStatusEnum.Active)
|
if (pet.Status != (int)UserPetStatusEnum.Active)
|
||||||
{
|
{
|
||||||
logger.LogWarning("喂养失败,宠物未激活,PetId: {PetId}, Status: {Status}", input.PetId, pet.Status);
|
logger.LogWarning("喂养失败,宠物未激活,PetId: {PetId}, Status: {Status}", input.PetId, pet.Status);
|
||||||
throw new BusinessException("宠物未激活,无法喂养", 400);
|
throw new BusinessException("宠物未激活,无法喂养", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
FeedPetOutput result = new FeedPetOutput();
|
FeedPetOutput result = new FeedPetOutput();
|
||||||
// 事务保证一致性
|
// 事务保证一致性
|
||||||
@ -273,13 +273,13 @@ public class PetService(
|
|||||||
// 查询宠物
|
// 查询宠物
|
||||||
var pet = await petRepository.GetByIdAsync(input.PetId);
|
var pet = await petRepository.GetByIdAsync(input.PetId);
|
||||||
if (pet == null || pet.IsDeleted)
|
if (pet == null || pet.IsDeleted)
|
||||||
throw new BusinessException("宠物不存在", 404);
|
throw new BusinessException("宠物不存在", ResultCode.NOT_FOUND);
|
||||||
|
|
||||||
if (pet.UserId != userId)
|
if (pet.UserId != userId)
|
||||||
throw new BusinessException("无权操作该宠物", 403);
|
throw new BusinessException("无权操作该宠物", ResultCode.FORBIDDEN);
|
||||||
|
|
||||||
if (pet.Status != (int)UserPetStatusEnum.Active)
|
if (pet.Status != (int)UserPetStatusEnum.Active)
|
||||||
throw new BusinessException("宠物未激活,无法喂养", 400);
|
throw new BusinessException("宠物未激活,无法喂养", ResultCode.BAD_REQUEST);
|
||||||
|
|
||||||
var growthBefore = pet.GrowthPoints;
|
var growthBefore = pet.GrowthPoints;
|
||||||
var growthAfter = growthBefore + input.GrowthPoints;
|
var growthAfter = growthBefore + input.GrowthPoints;
|
||||||
@ -297,7 +297,7 @@ public class PetService(
|
|||||||
|
|
||||||
if (updateResult <= 0)
|
if (updateResult <= 0)
|
||||||
{
|
{
|
||||||
throw new BusinessException("更新宠物成长值失败", 500);
|
throw new BusinessException("更新宠物成长值失败", ResultCode.GLOBAL_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 进化检查:查找下一阶段进化形态(PreviousEvolutionId 类型为 long?)
|
// 进化检查:查找下一阶段进化形态(PreviousEvolutionId 类型为 long?)
|
||||||
@ -348,7 +348,7 @@ public class PetService(
|
|||||||
var insertResult = await feedingRecordRepository.InsertAsync(record);
|
var insertResult = await feedingRecordRepository.InsertAsync(record);
|
||||||
if (!insertResult)
|
if (!insertResult)
|
||||||
{
|
{
|
||||||
throw new BusinessException("写入喂养记录失败", 500);
|
throw new BusinessException("写入喂养记录失败", ResultCode.GLOBAL_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.LogInformation("喂养宠物成功,PetId: {PetId}, 成长值: {Before} -> {After}, 进化: {HasEvolved}",
|
logger.LogInformation("喂养宠物成功,PetId: {PetId}, 成长值: {Before} -> {After}, 进化: {HasEvolved}",
|
||||||
@ -402,10 +402,10 @@ public class PetService(
|
|||||||
public async Task<PetTemplateOutput> CreateTemplateAsync(PetTemplateInput input)
|
public async Task<PetTemplateOutput> CreateTemplateAsync(PetTemplateInput input)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(input.Name))
|
if (string.IsNullOrWhiteSpace(input.Name))
|
||||||
throw new BusinessException("模板名称不能为空", 400);
|
throw new BusinessException("模板名称不能为空", ResultCode.BAD_REQUEST);
|
||||||
|
|
||||||
if (input.Evolutions == null || input.Evolutions.Count == 0)
|
if (input.Evolutions == null || input.Evolutions.Count == 0)
|
||||||
throw new BusinessException("至少需要一个进化阶段", 400);
|
throw new BusinessException("至少需要一个进化阶段", ResultCode.BAD_REQUEST);
|
||||||
|
|
||||||
PetTemplate template = null!;
|
PetTemplate template = null!;
|
||||||
|
|
||||||
@ -430,7 +430,7 @@ public class PetService(
|
|||||||
|
|
||||||
var inserted = await petTemplateRepository.InsertAsync(template);
|
var inserted = await petTemplateRepository.InsertAsync(template);
|
||||||
if (!inserted)
|
if (!inserted)
|
||||||
throw new BusinessException("创建宠物模板失败", 500);
|
throw new BusinessException("创建宠物模板失败", ResultCode.GLOBAL_ERROR);
|
||||||
|
|
||||||
// 2. 按 StageLevel 排序,依次创建进化阶段
|
// 2. 按 StageLevel 排序,依次创建进化阶段
|
||||||
var sortedEvolutions = input.Evolutions.OrderBy(e => e.StageLevel).ToList();
|
var sortedEvolutions = input.Evolutions.OrderBy(e => e.StageLevel).ToList();
|
||||||
@ -458,7 +458,7 @@ public class PetService(
|
|||||||
|
|
||||||
var evoInserted = await petEvolutionRepository.InsertAsync(evolution);
|
var evoInserted = await petEvolutionRepository.InsertAsync(evolution);
|
||||||
if (!evoInserted)
|
if (!evoInserted)
|
||||||
throw new BusinessException($"创建进化阶段 [{evoInput.StageName}] 失败", 500);
|
throw new BusinessException($"创建进化阶段 [{evoInput.StageName}] 失败", ResultCode.GLOBAL_ERROR);
|
||||||
|
|
||||||
// 记录初始阶段(第一个)
|
// 记录初始阶段(第一个)
|
||||||
if (previousEvolution == null)
|
if (previousEvolution == null)
|
||||||
@ -560,10 +560,10 @@ public class PetService(
|
|||||||
{
|
{
|
||||||
var template = await petTemplateRepository.GetByIdAsync(id);
|
var template = await petTemplateRepository.GetByIdAsync(id);
|
||||||
if (template == null || template.IsDeleted)
|
if (template == null || template.IsDeleted)
|
||||||
throw new BusinessException("宠物模板不存在", 404);
|
throw new BusinessException("宠物模板不存在", ResultCode.NOT_FOUND);
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(input.Name))
|
if (string.IsNullOrWhiteSpace(input.Name))
|
||||||
throw new BusinessException("模板名称不能为空", 400);
|
throw new BusinessException("模板名称不能为空", ResultCode.BAD_REQUEST);
|
||||||
|
|
||||||
template.Name = input.Name.Trim();
|
template.Name = input.Name.Trim();
|
||||||
template.Description = input.Description;
|
template.Description = input.Description;
|
||||||
@ -575,7 +575,7 @@ public class PetService(
|
|||||||
|
|
||||||
var result = await petTemplateRepository.UpdateAsync(template);
|
var result = await petTemplateRepository.UpdateAsync(template);
|
||||||
if (!result)
|
if (!result)
|
||||||
throw new BusinessException("更新宠物模板失败", 500);
|
throw new BusinessException("更新宠物模板失败", ResultCode.GLOBAL_ERROR);
|
||||||
|
|
||||||
logger.LogInformation("更新宠物模板成功,Id: {Id}", id);
|
logger.LogInformation("更新宠物模板成功,Id: {Id}", id);
|
||||||
return BuildTemplateOutput(template);
|
return BuildTemplateOutput(template);
|
||||||
@ -588,18 +588,18 @@ public class PetService(
|
|||||||
{
|
{
|
||||||
var template = await petTemplateRepository.GetByIdAsync(id);
|
var template = await petTemplateRepository.GetByIdAsync(id);
|
||||||
if (template == null || template.IsDeleted)
|
if (template == null || template.IsDeleted)
|
||||||
throw new BusinessException("宠物模板不存在", 404);
|
throw new BusinessException("宠物模板不存在", ResultCode.NOT_FOUND);
|
||||||
|
|
||||||
|
|
||||||
if (template.Type == PetTemplateTypeEnum.Default)
|
if (template.Type == PetTemplateTypeEnum.Default)
|
||||||
throw new BusinessException("默认模板不允许删除", 400);
|
throw new BusinessException("默认模板不允许删除", ResultCode.BAD_REQUEST);
|
||||||
|
|
||||||
|
|
||||||
// 校验是否有用户宠物实例关联
|
// 校验是否有用户宠物实例关联
|
||||||
var hasUserPet = petRepository.Context.Queryable<UserPet>()
|
var hasUserPet = petRepository.Context.Queryable<UserPet>()
|
||||||
.Any(p => p.TemplateId == id && !p.IsDeleted);
|
.Any(p => p.TemplateId == id && !p.IsDeleted);
|
||||||
if (hasUserPet)
|
if (hasUserPet)
|
||||||
throw new BusinessException("该模板下存在用户宠物实例,无法删除", 400);
|
throw new BusinessException("该模板下存在用户宠物实例,无法删除", ResultCode.BAD_REQUEST);
|
||||||
|
|
||||||
template.IsDeleted = true;
|
template.IsDeleted = true;
|
||||||
template.UpdatedBy = "System";
|
template.UpdatedBy = "System";
|
||||||
@ -616,7 +616,7 @@ public class PetService(
|
|||||||
{
|
{
|
||||||
var template = await petTemplateRepository.GetByIdAsync(id);
|
var template = await petTemplateRepository.GetByIdAsync(id);
|
||||||
if (template == null || template.IsDeleted)
|
if (template == null || template.IsDeleted)
|
||||||
throw new BusinessException("宠物模板不存在", 404);
|
throw new BusinessException("宠物模板不存在", ResultCode.NOT_FOUND);
|
||||||
|
|
||||||
return BuildTemplateOutput(template);
|
return BuildTemplateOutput(template);
|
||||||
}
|
}
|
||||||
@ -663,7 +663,7 @@ public class PetService(
|
|||||||
{
|
{
|
||||||
var template = await petTemplateRepository.GetByIdAsync(id);
|
var template = await petTemplateRepository.GetByIdAsync(id);
|
||||||
if (template == null || template.IsDeleted)
|
if (template == null || template.IsDeleted)
|
||||||
throw new BusinessException("宠物模板不存在", 404);
|
throw new BusinessException("宠物模板不存在", ResultCode.NOT_FOUND);
|
||||||
|
|
||||||
template.Status = template.Status == (int)DefaultStatusEnum.Active
|
template.Status = template.Status == (int)DefaultStatusEnum.Active
|
||||||
? (int)DefaultStatusEnum.Inactive
|
? (int)DefaultStatusEnum.Inactive
|
||||||
@ -703,16 +703,16 @@ public class PetService(
|
|||||||
public async Task<PetEvolutionOutput> CreateEvolutionAsync(PetEvolutionInput input)
|
public async Task<PetEvolutionOutput> CreateEvolutionAsync(PetEvolutionInput input)
|
||||||
{
|
{
|
||||||
if (input.TemplateId <= 0)
|
if (input.TemplateId <= 0)
|
||||||
throw new BusinessException("模板Id不能为空", 400);
|
throw new BusinessException("模板Id不能为空", ResultCode.BAD_REQUEST);
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(input.StageName))
|
if (string.IsNullOrWhiteSpace(input.StageName))
|
||||||
throw new BusinessException("阶段名称不能为空", 400);
|
throw new BusinessException("阶段名称不能为空", ResultCode.BAD_REQUEST);
|
||||||
|
|
||||||
// 校验模板是否存在
|
// 校验模板是否存在
|
||||||
var templateExists = petTemplateRepository.Context.Queryable<PetTemplate>()
|
var templateExists = petTemplateRepository.Context.Queryable<PetTemplate>()
|
||||||
.Any(t => t.Id == input.TemplateId && !t.IsDeleted);
|
.Any(t => t.Id == input.TemplateId && !t.IsDeleted);
|
||||||
if (!templateExists)
|
if (!templateExists)
|
||||||
throw new BusinessException("宠物模板不存在", 404);
|
throw new BusinessException("宠物模板不存在", ResultCode.NOT_FOUND);
|
||||||
|
|
||||||
var evolution = new PetEvolution
|
var evolution = new PetEvolution
|
||||||
{
|
{
|
||||||
@ -732,7 +732,7 @@ public class PetService(
|
|||||||
|
|
||||||
var result = await petEvolutionRepository.InsertAsync(evolution);
|
var result = await petEvolutionRepository.InsertAsync(evolution);
|
||||||
if (!result)
|
if (!result)
|
||||||
throw new BusinessException("创建进化阶段失败", 500);
|
throw new BusinessException("创建进化阶段失败", ResultCode.GLOBAL_ERROR);
|
||||||
|
|
||||||
logger.LogInformation("创建进化阶段成功,Id: {Id}, StageName: {StageName}", evolution.Id, evolution.StageName);
|
logger.LogInformation("创建进化阶段成功,Id: {Id}, StageName: {StageName}", evolution.Id, evolution.StageName);
|
||||||
return BuildEvolutionOutput(evolution);
|
return BuildEvolutionOutput(evolution);
|
||||||
@ -745,10 +745,10 @@ public class PetService(
|
|||||||
{
|
{
|
||||||
var evolution = await petEvolutionRepository.GetByIdAsync(id);
|
var evolution = await petEvolutionRepository.GetByIdAsync(id);
|
||||||
if (evolution == null || evolution.IsDeleted)
|
if (evolution == null || evolution.IsDeleted)
|
||||||
throw new BusinessException("进化阶段不存在", 404);
|
throw new BusinessException("进化阶段不存在", ResultCode.NOT_FOUND);
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(input.StageName))
|
if (string.IsNullOrWhiteSpace(input.StageName))
|
||||||
throw new BusinessException("阶段名称不能为空", 400);
|
throw new BusinessException("阶段名称不能为空", ResultCode.BAD_REQUEST);
|
||||||
|
|
||||||
evolution.TemplateId = input.TemplateId;
|
evolution.TemplateId = input.TemplateId;
|
||||||
evolution.StageName = input.StageName.Trim();
|
evolution.StageName = input.StageName.Trim();
|
||||||
@ -761,7 +761,7 @@ public class PetService(
|
|||||||
|
|
||||||
var result = await petEvolutionRepository.UpdateAsync(evolution);
|
var result = await petEvolutionRepository.UpdateAsync(evolution);
|
||||||
if (!result)
|
if (!result)
|
||||||
throw new BusinessException("更新进化阶段失败", 500);
|
throw new BusinessException("更新进化阶段失败", ResultCode.GLOBAL_ERROR);
|
||||||
|
|
||||||
logger.LogInformation("更新进化阶段成功,Id: {Id}", id);
|
logger.LogInformation("更新进化阶段成功,Id: {Id}", id);
|
||||||
return BuildEvolutionOutput(evolution);
|
return BuildEvolutionOutput(evolution);
|
||||||
@ -774,13 +774,13 @@ public class PetService(
|
|||||||
{
|
{
|
||||||
var evolution = await petEvolutionRepository.GetByIdAsync(id);
|
var evolution = await petEvolutionRepository.GetByIdAsync(id);
|
||||||
if (evolution == null || evolution.IsDeleted)
|
if (evolution == null || evolution.IsDeleted)
|
||||||
throw new BusinessException("进化阶段不存在", 404);
|
throw new BusinessException("进化阶段不存在", ResultCode.NOT_FOUND);
|
||||||
|
|
||||||
// 校验是否有用户宠物处于该形态
|
// 校验是否有用户宠物处于该形态
|
||||||
var hasUserPet = petRepository.Context.Queryable<UserPet>()
|
var hasUserPet = petRepository.Context.Queryable<UserPet>()
|
||||||
.Any(p => p.CurrentEvolutionId == id && !p.IsDeleted);
|
.Any(p => p.CurrentEvolutionId == id && !p.IsDeleted);
|
||||||
if (hasUserPet)
|
if (hasUserPet)
|
||||||
throw new BusinessException("有用户宠物正处于该形态,无法删除", 400);
|
throw new BusinessException("有用户宠物正处于该形态,无法删除", ResultCode.BAD_REQUEST);
|
||||||
|
|
||||||
evolution.IsDeleted = true;
|
evolution.IsDeleted = true;
|
||||||
evolution.UpdatedBy = "System";
|
evolution.UpdatedBy = "System";
|
||||||
@ -797,7 +797,7 @@ public class PetService(
|
|||||||
{
|
{
|
||||||
var evolution = await petEvolutionRepository.GetByIdAsync(id);
|
var evolution = await petEvolutionRepository.GetByIdAsync(id);
|
||||||
if (evolution == null || evolution.IsDeleted)
|
if (evolution == null || evolution.IsDeleted)
|
||||||
throw new BusinessException("进化阶段不存在", 404);
|
throw new BusinessException("进化阶段不存在", ResultCode.NOT_FOUND);
|
||||||
|
|
||||||
return BuildEvolutionOutput(evolution);
|
return BuildEvolutionOutput(evolution);
|
||||||
}
|
}
|
||||||
@ -861,16 +861,16 @@ public class PetService(
|
|||||||
public async Task<PetSkinOutput> CreateSkinAsync(PetSkinInput input)
|
public async Task<PetSkinOutput> CreateSkinAsync(PetSkinInput input)
|
||||||
{
|
{
|
||||||
if (input.TemplateId <= 0)
|
if (input.TemplateId <= 0)
|
||||||
throw new BusinessException("模板Id不能为空", 400);
|
throw new BusinessException("模板Id不能为空", ResultCode.BAD_REQUEST);
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(input.Name))
|
if (string.IsNullOrWhiteSpace(input.Name))
|
||||||
throw new BusinessException("皮肤名称不能为空", 400);
|
throw new BusinessException("皮肤名称不能为空", ResultCode.BAD_REQUEST);
|
||||||
|
|
||||||
// 校验模板是否存在
|
// 校验模板是否存在
|
||||||
var templateExists = petTemplateRepository.Context.Queryable<PetTemplate>()
|
var templateExists = petTemplateRepository.Context.Queryable<PetTemplate>()
|
||||||
.Any(t => t.Id == input.TemplateId && !t.IsDeleted);
|
.Any(t => t.Id == input.TemplateId && !t.IsDeleted);
|
||||||
if (!templateExists)
|
if (!templateExists)
|
||||||
throw new BusinessException("宠物模板不存在", 404);
|
throw new BusinessException("宠物模板不存在", ResultCode.NOT_FOUND);
|
||||||
|
|
||||||
var skin = new PetSkin
|
var skin = new PetSkin
|
||||||
{
|
{
|
||||||
@ -890,7 +890,7 @@ public class PetService(
|
|||||||
|
|
||||||
var result = await petSkinRepository.InsertAsync(skin);
|
var result = await petSkinRepository.InsertAsync(skin);
|
||||||
if (!result)
|
if (!result)
|
||||||
throw new BusinessException("创建皮肤失败", 500);
|
throw new BusinessException("创建皮肤失败", ResultCode.GLOBAL_ERROR);
|
||||||
|
|
||||||
// 搬运封面图到正式目录
|
// 搬运封面图到正式目录
|
||||||
if (OssImageHelper.IsTempImage(skin.CoverImageUrl))
|
if (OssImageHelper.IsTempImage(skin.CoverImageUrl))
|
||||||
@ -911,10 +911,10 @@ public class PetService(
|
|||||||
{
|
{
|
||||||
var skin = await petSkinRepository.GetByIdAsync(id);
|
var skin = await petSkinRepository.GetByIdAsync(id);
|
||||||
if (skin == null || skin.IsDeleted)
|
if (skin == null || skin.IsDeleted)
|
||||||
throw new BusinessException("皮肤不存在", 404);
|
throw new BusinessException("皮肤不存在", ResultCode.NOT_FOUND);
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(input.Name))
|
if (string.IsNullOrWhiteSpace(input.Name))
|
||||||
throw new BusinessException("皮肤名称不能为空", 400);
|
throw new BusinessException("皮肤名称不能为空", ResultCode.BAD_REQUEST);
|
||||||
|
|
||||||
skin.TemplateId = input.TemplateId;
|
skin.TemplateId = input.TemplateId;
|
||||||
skin.Name = input.Name.Trim();
|
skin.Name = input.Name.Trim();
|
||||||
@ -937,7 +937,7 @@ public class PetService(
|
|||||||
|
|
||||||
var result = await petSkinRepository.UpdateAsync(skin);
|
var result = await petSkinRepository.UpdateAsync(skin);
|
||||||
if (!result)
|
if (!result)
|
||||||
throw new BusinessException("更新皮肤失败", 500);
|
throw new BusinessException("更新皮肤失败", ResultCode.GLOBAL_ERROR);
|
||||||
|
|
||||||
logger.LogInformation("更新皮肤成功,Id: {Id}", id);
|
logger.LogInformation("更新皮肤成功,Id: {Id}", id);
|
||||||
|
|
||||||
@ -957,13 +957,13 @@ public class PetService(
|
|||||||
{
|
{
|
||||||
var skin = await petSkinRepository.GetByIdAsync(id);
|
var skin = await petSkinRepository.GetByIdAsync(id);
|
||||||
if (skin == null || skin.IsDeleted)
|
if (skin == null || skin.IsDeleted)
|
||||||
throw new BusinessException("皮肤不存在", 404);
|
throw new BusinessException("皮肤不存在", ResultCode.NOT_FOUND);
|
||||||
|
|
||||||
// 校验是否有用户宠物正在使用该皮肤
|
// 校验是否有用户宠物正在使用该皮肤
|
||||||
var inUse = petRepository.Context.Queryable<UserPet>()
|
var inUse = petRepository.Context.Queryable<UserPet>()
|
||||||
.Any(p => p.CurrentSkinId == id && !p.IsDeleted);
|
.Any(p => p.CurrentSkinId == id && !p.IsDeleted);
|
||||||
if (inUse)
|
if (inUse)
|
||||||
throw new BusinessException("有用户宠物正在使用该皮肤,无法删除", 400);
|
throw new BusinessException("有用户宠物正在使用该皮肤,无法删除", ResultCode.BAD_REQUEST);
|
||||||
|
|
||||||
skin.IsDeleted = true;
|
skin.IsDeleted = true;
|
||||||
skin.UpdatedBy = "System";
|
skin.UpdatedBy = "System";
|
||||||
@ -980,7 +980,7 @@ public class PetService(
|
|||||||
{
|
{
|
||||||
var skin = await petSkinRepository.GetByIdAsync(id);
|
var skin = await petSkinRepository.GetByIdAsync(id);
|
||||||
if (skin == null || skin.IsDeleted)
|
if (skin == null || skin.IsDeleted)
|
||||||
throw new BusinessException("皮肤不存在", 404);
|
throw new BusinessException("皮肤不存在", ResultCode.NOT_FOUND);
|
||||||
|
|
||||||
var images = await petSkinImageRepository.Queryable()
|
var images = await petSkinImageRepository.Queryable()
|
||||||
.Where(i => i.SkinId == id && !i.IsDeleted)
|
.Where(i => i.SkinId == id && !i.IsDeleted)
|
||||||
@ -1072,19 +1072,19 @@ public class PetService(
|
|||||||
public async Task<PetSkinImageOutput> CreateSkinImageAsync(PetSkinImageInput input)
|
public async Task<PetSkinImageOutput> CreateSkinImageAsync(PetSkinImageInput input)
|
||||||
{
|
{
|
||||||
if (input.SkinId <= 0)
|
if (input.SkinId <= 0)
|
||||||
throw new BusinessException("皮肤Id不能为空", 400);
|
throw new BusinessException("皮肤Id不能为空", ResultCode.BAD_REQUEST);
|
||||||
|
|
||||||
if (input.EvolutionStageId <= 0)
|
if (input.EvolutionStageId <= 0)
|
||||||
throw new BusinessException("进化阶段Id不能为空", 400);
|
throw new BusinessException("进化阶段Id不能为空", ResultCode.BAD_REQUEST);
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(input.ImageUrl))
|
if (string.IsNullOrWhiteSpace(input.ImageUrl))
|
||||||
throw new BusinessException("图片地址不能为空", 400);
|
throw new BusinessException("图片地址不能为空", ResultCode.BAD_REQUEST);
|
||||||
|
|
||||||
// 校验皮肤是否存在
|
// 校验皮肤是否存在
|
||||||
var skinExists = petSkinRepository.Context.Queryable<PetSkin>()
|
var skinExists = petSkinRepository.Context.Queryable<PetSkin>()
|
||||||
.Any(s => s.Id == input.SkinId && !s.IsDeleted);
|
.Any(s => s.Id == input.SkinId && !s.IsDeleted);
|
||||||
if (!skinExists)
|
if (!skinExists)
|
||||||
throw new BusinessException("皮肤不存在", 404);
|
throw new BusinessException("皮肤不存在", ResultCode.NOT_FOUND);
|
||||||
|
|
||||||
var image = new PetSkinImage
|
var image = new PetSkinImage
|
||||||
{
|
{
|
||||||
@ -1102,7 +1102,7 @@ public class PetService(
|
|||||||
|
|
||||||
var result = await petSkinImageRepository.InsertAsync(image);
|
var result = await petSkinImageRepository.InsertAsync(image);
|
||||||
if (!result)
|
if (!result)
|
||||||
throw new BusinessException("创建皮肤图片失败", 500);
|
throw new BusinessException("创建皮肤图片失败", ResultCode.GLOBAL_ERROR);
|
||||||
|
|
||||||
// 搬运图片到正式目录
|
// 搬运图片到正式目录
|
||||||
if (OssImageHelper.IsTempImage(image.ImageUrl))
|
if (OssImageHelper.IsTempImage(image.ImageUrl))
|
||||||
@ -1123,10 +1123,10 @@ public class PetService(
|
|||||||
{
|
{
|
||||||
var image = await petSkinImageRepository.GetByIdAsync(id);
|
var image = await petSkinImageRepository.GetByIdAsync(id);
|
||||||
if (image == null || image.IsDeleted)
|
if (image == null || image.IsDeleted)
|
||||||
throw new BusinessException("皮肤图片不存在", 404);
|
throw new BusinessException("皮肤图片不存在", ResultCode.NOT_FOUND);
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(input.ImageUrl))
|
if (string.IsNullOrWhiteSpace(input.ImageUrl))
|
||||||
throw new BusinessException("图片地址不能为空", 400);
|
throw new BusinessException("图片地址不能为空", ResultCode.BAD_REQUEST);
|
||||||
|
|
||||||
image.SkinId = input.SkinId;
|
image.SkinId = input.SkinId;
|
||||||
image.EvolutionStageId = input.EvolutionStageId;
|
image.EvolutionStageId = input.EvolutionStageId;
|
||||||
@ -1147,7 +1147,7 @@ public class PetService(
|
|||||||
|
|
||||||
var result = await petSkinImageRepository.UpdateAsync(image);
|
var result = await petSkinImageRepository.UpdateAsync(image);
|
||||||
if (!result)
|
if (!result)
|
||||||
throw new BusinessException("更新皮肤图片失败", 500);
|
throw new BusinessException("更新皮肤图片失败", ResultCode.GLOBAL_ERROR);
|
||||||
|
|
||||||
logger.LogInformation("更新皮肤图片成功,Id: {Id}", id);
|
logger.LogInformation("更新皮肤图片成功,Id: {Id}", id);
|
||||||
return BuildSkinImageOutput(image);
|
return BuildSkinImageOutput(image);
|
||||||
@ -1160,7 +1160,7 @@ public class PetService(
|
|||||||
{
|
{
|
||||||
var image = await petSkinImageRepository.GetByIdAsync(id);
|
var image = await petSkinImageRepository.GetByIdAsync(id);
|
||||||
if (image == null || image.IsDeleted)
|
if (image == null || image.IsDeleted)
|
||||||
throw new BusinessException("皮肤图片不存在", 404);
|
throw new BusinessException("皮肤图片不存在", ResultCode.NOT_FOUND);
|
||||||
|
|
||||||
image.IsDeleted = true;
|
image.IsDeleted = true;
|
||||||
image.UpdatedBy = "System";
|
image.UpdatedBy = "System";
|
||||||
@ -1208,7 +1208,7 @@ public class PetService(
|
|||||||
public async Task<List<PetEvolutionOutput>> GetEvolutionsByTemplateIdAsync(long templateId)
|
public async Task<List<PetEvolutionOutput>> GetEvolutionsByTemplateIdAsync(long templateId)
|
||||||
{
|
{
|
||||||
if (templateId <= 0)
|
if (templateId <= 0)
|
||||||
throw new BusinessException("模板Id不能为空", 400);
|
throw new BusinessException("模板Id不能为空", ResultCode.BAD_REQUEST);
|
||||||
|
|
||||||
var list = await petEvolutionRepository.Queryable()
|
var list = await petEvolutionRepository.Queryable()
|
||||||
.Where(e => e.TemplateId == templateId && !e.IsDeleted)
|
.Where(e => e.TemplateId == templateId && !e.IsDeleted)
|
||||||
@ -1224,7 +1224,7 @@ public class PetService(
|
|||||||
public async Task<List<PetSkinOutput>> GetSkinsByTemplateIdAsync(long templateId)
|
public async Task<List<PetSkinOutput>> GetSkinsByTemplateIdAsync(long templateId)
|
||||||
{
|
{
|
||||||
if (templateId <= 0)
|
if (templateId <= 0)
|
||||||
throw new BusinessException("模板Id不能为空", 400);
|
throw new BusinessException("模板Id不能为空", ResultCode.BAD_REQUEST);
|
||||||
|
|
||||||
var list = await petSkinRepository.Queryable()
|
var list = await petSkinRepository.Queryable()
|
||||||
.Where(s => s.TemplateId == templateId && !s.IsDeleted)
|
.Where(s => s.TemplateId == templateId && !s.IsDeleted)
|
||||||
@ -1276,12 +1276,12 @@ public class PetService(
|
|||||||
public async Task<List<SkinEvolutionStageOutput>> GetSkinImagesGroupedBySkinIdAsync(long skinId)
|
public async Task<List<SkinEvolutionStageOutput>> GetSkinImagesGroupedBySkinIdAsync(long skinId)
|
||||||
{
|
{
|
||||||
if (skinId <= 0)
|
if (skinId <= 0)
|
||||||
throw new BusinessException("皮肤Id不能为空", 400);
|
throw new BusinessException("皮肤Id不能为空", ResultCode.BAD_REQUEST);
|
||||||
|
|
||||||
// 1. 获取皮肤信息
|
// 1. 获取皮肤信息
|
||||||
var skin = await petSkinRepository.GetByIdAsync(skinId);
|
var skin = await petSkinRepository.GetByIdAsync(skinId);
|
||||||
if (skin == null || skin.IsDeleted)
|
if (skin == null || skin.IsDeleted)
|
||||||
throw new BusinessException("皮肤不存在", 404);
|
throw new BusinessException("皮肤不存在", ResultCode.NOT_FOUND);
|
||||||
|
|
||||||
// 2. 获取该模板的所有进化阶段(按阶段等级排序)
|
// 2. 获取该模板的所有进化阶段(按阶段等级排序)
|
||||||
var evolutions = await petEvolutionRepository.Queryable()
|
var evolutions = await petEvolutionRepository.Queryable()
|
||||||
|
|||||||
@ -28,7 +28,7 @@ public class PointsService(
|
|||||||
input.UserId, input.Amount, input.ChangeType);
|
input.UserId, input.Amount, input.ChangeType);
|
||||||
|
|
||||||
if (input.Amount <= 0)
|
if (input.Amount <= 0)
|
||||||
throw new BusinessException("增加积分数量必须大于0", 400);
|
throw new BusinessException("增加积分数量必须大于0", ResultCode.BAD_REQUEST);
|
||||||
|
|
||||||
AddPointsOutput result = null!;
|
AddPointsOutput result = null!;
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ public class PointsService(
|
|||||||
input.UserId, input.Amount, input.ChangeType);
|
input.UserId, input.Amount, input.ChangeType);
|
||||||
|
|
||||||
if (input.Amount <= 0)
|
if (input.Amount <= 0)
|
||||||
throw new BusinessException("扣除积分数量必须大于0", 400);
|
throw new BusinessException("扣除积分数量必须大于0", ResultCode.BAD_REQUEST);
|
||||||
|
|
||||||
DeductPointsOutput result = null!;
|
DeductPointsOutput result = null!;
|
||||||
|
|
||||||
@ -71,7 +71,7 @@ public class PointsService(
|
|||||||
public async Task<AddPointsOutput> AddPointsInTranAsync(AddPointsInput input)
|
public async Task<AddPointsOutput> AddPointsInTranAsync(AddPointsInput input)
|
||||||
{
|
{
|
||||||
if (input.Amount <= 0)
|
if (input.Amount <= 0)
|
||||||
throw new BusinessException("增加积分数量必须大于0", 400);
|
throw new BusinessException("增加积分数量必须大于0", ResultCode.BAD_REQUEST);
|
||||||
|
|
||||||
// 查询用户当前积分
|
// 查询用户当前积分
|
||||||
var user = await Context.Queryable<Users>()
|
var user = await Context.Queryable<Users>()
|
||||||
@ -79,7 +79,7 @@ public class PointsService(
|
|||||||
.FirstAsync();
|
.FirstAsync();
|
||||||
|
|
||||||
if (user == null)
|
if (user == null)
|
||||||
throw new BusinessException("用户不存在", 404);
|
throw new BusinessException("用户不存在", ResultCode.NOT_FOUND);
|
||||||
|
|
||||||
var previousBalance = user.Points;
|
var previousBalance = user.Points;
|
||||||
var newBalance = previousBalance + input.Amount;
|
var newBalance = previousBalance + input.Amount;
|
||||||
@ -129,7 +129,7 @@ public class PointsService(
|
|||||||
public async Task<DeductPointsOutput> DeductPointsInTranAsync(DeductPointsInput input)
|
public async Task<DeductPointsOutput> DeductPointsInTranAsync(DeductPointsInput input)
|
||||||
{
|
{
|
||||||
if (input.Amount <= 0)
|
if (input.Amount <= 0)
|
||||||
throw new BusinessException("扣除积分数量必须大于0", 400);
|
throw new BusinessException("扣除积分数量必须大于0", ResultCode.BAD_REQUEST);
|
||||||
|
|
||||||
// 查询用户当前积分
|
// 查询用户当前积分
|
||||||
var user = await Context.Queryable<Users>()
|
var user = await Context.Queryable<Users>()
|
||||||
@ -137,13 +137,13 @@ public class PointsService(
|
|||||||
.FirstAsync();
|
.FirstAsync();
|
||||||
|
|
||||||
if (user == null)
|
if (user == null)
|
||||||
throw new BusinessException("用户不存在", 404);
|
throw new BusinessException("用户不存在", ResultCode.NOT_FOUND);
|
||||||
|
|
||||||
var previousBalance = user.Points;
|
var previousBalance = user.Points;
|
||||||
|
|
||||||
// 余额不足校验
|
// 余额不足校验
|
||||||
if (previousBalance < input.Amount)
|
if (previousBalance < input.Amount)
|
||||||
throw new BusinessException($"积分不足,需要 {input.Amount} 积分,当前余额 {previousBalance}", 400);
|
throw new BusinessException($"积分不足,需要 {input.Amount} 积分,当前余额 {previousBalance}", ResultCode.BAD_REQUEST);
|
||||||
|
|
||||||
var newBalance = previousBalance - input.Amount;
|
var newBalance = previousBalance - input.Amount;
|
||||||
|
|
||||||
@ -214,7 +214,7 @@ public class PointsService(
|
|||||||
.FirstAsync();
|
.FirstAsync();
|
||||||
|
|
||||||
if (user == null)
|
if (user == null)
|
||||||
throw new BusinessException("用户不存在", 404);
|
throw new BusinessException("用户不存在", ResultCode.NOT_FOUND);
|
||||||
|
|
||||||
// 查询累计收入(Income 类型)
|
// 查询累计收入(Income 类型)
|
||||||
var totalIncome = await Context.Queryable<PointsRecord>()
|
var totalIncome = await Context.Queryable<PointsRecord>()
|
||||||
@ -241,10 +241,10 @@ public class PointsService(
|
|||||||
public async Task<PageListModel<PointsRecordOutput>> GetPointsRecordsAsync(PointsRecordQueryInput input)
|
public async Task<PageListModel<PointsRecordOutput>> GetPointsRecordsAsync(PointsRecordQueryInput input)
|
||||||
{
|
{
|
||||||
if (input.PageIndex <= 0)
|
if (input.PageIndex <= 0)
|
||||||
throw new BusinessException("页码必须大于0", 400);
|
throw new BusinessException("页码必须大于0", ResultCode.BAD_REQUEST);
|
||||||
|
|
||||||
if (input.PageSize <= 0 || input.PageSize > 100)
|
if (input.PageSize <= 0 || input.PageSize > 100)
|
||||||
throw new BusinessException("每页条数必须在1-100之间", 400);
|
throw new BusinessException("每页条数必须在1-100之间", ResultCode.BAD_REQUEST);
|
||||||
|
|
||||||
var query = Context.Queryable<PointsRecord>()
|
var query = Context.Queryable<PointsRecord>()
|
||||||
.Where(r => r.UserId == input.UserId && !r.IsDeleted)
|
.Where(r => r.UserId == input.UserId && !r.IsDeleted)
|
||||||
|
|||||||
@ -29,17 +29,17 @@ public class ProductService(
|
|||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(input.Name))
|
if (string.IsNullOrWhiteSpace(input.Name))
|
||||||
{
|
{
|
||||||
throw new BusinessException("商品名称不能为空", 400);
|
throw new BusinessException("商品名称不能为空", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(input.Type))
|
if (string.IsNullOrWhiteSpace(input.Type))
|
||||||
{
|
{
|
||||||
throw new BusinessException("商品类型不能为空", 400);
|
throw new BusinessException("商品类型不能为空", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input.Price < 0)
|
if (input.Price < 0)
|
||||||
{
|
{
|
||||||
throw new BusinessException("商品价格不能为负数", 400);
|
throw new BusinessException("商品价格不能为负数", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
var product = new Product
|
var product = new Product
|
||||||
@ -66,7 +66,7 @@ public class ProductService(
|
|||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
logger.LogError("商品创建失败,商品名称: {Name}", input.Name);
|
logger.LogError("商品创建失败,商品名称: {Name}", input.Name);
|
||||||
throw new BusinessException("创建商品失败", 500);
|
throw new BusinessException("创建商品失败", ResultCode.GLOBAL_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 将 temp 目录下的图片搬运到正式目录
|
// 将 temp 目录下的图片搬运到正式目录
|
||||||
@ -113,22 +113,22 @@ public class ProductService(
|
|||||||
if (product == null)
|
if (product == null)
|
||||||
{
|
{
|
||||||
logger.LogWarning("未找到要更新的商品,ID: {Id}", id);
|
logger.LogWarning("未找到要更新的商品,ID: {Id}", id);
|
||||||
throw new BusinessException("商品不存在", 404);
|
throw new BusinessException("商品不存在", ResultCode.NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(input.Name))
|
if (string.IsNullOrWhiteSpace(input.Name))
|
||||||
{
|
{
|
||||||
throw new BusinessException("商品名称不能为空", 400);
|
throw new BusinessException("商品名称不能为空", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(input.Type))
|
if (string.IsNullOrWhiteSpace(input.Type))
|
||||||
{
|
{
|
||||||
throw new BusinessException("商品类型不能为空", 400);
|
throw new BusinessException("商品类型不能为空", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input.Price < 0)
|
if (input.Price < 0)
|
||||||
{
|
{
|
||||||
throw new BusinessException("商品价格不能为负数", 400);
|
throw new BusinessException("商品价格不能为负数", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 将 temp 目录下的新图片搬运到正式目录
|
// 将 temp 目录下的新图片搬运到正式目录
|
||||||
@ -158,7 +158,7 @@ public class ProductService(
|
|||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
logger.LogError("商品更新失败,ID: {Id}", id);
|
logger.LogError("商品更新失败,ID: {Id}", id);
|
||||||
throw new BusinessException("更新商品失败", 500);
|
throw new BusinessException("更新商品失败", ResultCode.GLOBAL_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.LogInformation("商品更新成功,ID: {Id}", id);
|
logger.LogInformation("商品更新成功,ID: {Id}", id);
|
||||||
@ -195,14 +195,14 @@ public class ProductService(
|
|||||||
if (product == null)
|
if (product == null)
|
||||||
{
|
{
|
||||||
logger.LogWarning("未找到要删除的商品,ID: {Id}", id);
|
logger.LogWarning("未找到要删除的商品,ID: {Id}", id);
|
||||||
throw new BusinessException("商品不存在", 404);
|
throw new BusinessException("商品不存在", ResultCode.NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = await productRepository.DeleteByIdAsync(id);
|
var result = await productRepository.DeleteByIdAsync(id);
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
logger.LogError("商品删除失败,ID: {Id}", id);
|
logger.LogError("商品删除失败,ID: {Id}", id);
|
||||||
throw new BusinessException("删除商品失败", 500);
|
throw new BusinessException("删除商品失败", ResultCode.GLOBAL_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.LogInformation("商品删除成功,ID: {Id}", id);
|
logger.LogInformation("商品删除成功,ID: {Id}", id);
|
||||||
@ -219,7 +219,7 @@ public class ProductService(
|
|||||||
if (product == null)
|
if (product == null)
|
||||||
{
|
{
|
||||||
logger.LogWarning("未找到商品,ID: {Id}", id);
|
logger.LogWarning("未找到商品,ID: {Id}", id);
|
||||||
throw new BusinessException("商品不存在", 404);
|
throw new BusinessException("商品不存在", ResultCode.NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ProductOutput
|
return new ProductOutput
|
||||||
@ -252,12 +252,12 @@ public class ProductService(
|
|||||||
|
|
||||||
if (input.PageIndex <= 0)
|
if (input.PageIndex <= 0)
|
||||||
{
|
{
|
||||||
throw new BusinessException("页码必须大于0", 400);
|
throw new BusinessException("页码必须大于0", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input.PageSize <= 0 || input.PageSize > 100)
|
if (input.PageSize <= 0 || input.PageSize > 100)
|
||||||
{
|
{
|
||||||
throw new BusinessException("每页条数必须在1-100之间", 400);
|
throw new BusinessException("每页条数必须在1-100之间", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
RefAsync<int> totalNumber = 0;
|
RefAsync<int> totalNumber = 0;
|
||||||
@ -303,7 +303,7 @@ public class ProductService(
|
|||||||
if (product == null)
|
if (product == null)
|
||||||
{
|
{
|
||||||
logger.LogWarning("未找到要更新状态的商品,ID: {Id}", id);
|
logger.LogWarning("未找到要更新状态的商品,ID: {Id}", id);
|
||||||
throw new BusinessException("商品不存在", 404);
|
throw new BusinessException("商品不存在", ResultCode.NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
product.Status = product.Status == (int)ProductStatusEnum.OnSale
|
product.Status = product.Status == (int)ProductStatusEnum.OnSale
|
||||||
@ -316,7 +316,7 @@ public class ProductService(
|
|||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
logger.LogError("商品状态更新失败,ID: {Id}", id);
|
logger.LogError("商品状态更新失败,ID: {Id}", id);
|
||||||
throw new BusinessException("更新商品状态失败", 500);
|
throw new BusinessException("更新商品状态失败", ResultCode.GLOBAL_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.LogInformation("商品上下架状态更新成功,ID: {Id}, SaleStatus: {SaleStatus}", id, product.Status);
|
logger.LogInformation("商品上下架状态更新成功,ID: {Id}, SaleStatus: {SaleStatus}", id, product.Status);
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using QYZH.InteractiveMagazine.IService;
|
using QYZH.InteractiveMagazine.IService;
|
||||||
using QYZH.InteractiveMagazine.Models.Common;
|
using QYZH.InteractiveMagazine.Models.Common;
|
||||||
|
using QYZH.InteractiveMagazine.Models.Dto;
|
||||||
using QYZH.InteractiveMagazine.Models.Dto.Points;
|
using QYZH.InteractiveMagazine.Models.Dto.Points;
|
||||||
using QYZH.InteractiveMagazine.Models.Dto.UserAnswerTaskService;
|
using QYZH.InteractiveMagazine.Models.Dto.UserAnswerTaskService;
|
||||||
using QYZH.InteractiveMagazine.Models.Entity;
|
using QYZH.InteractiveMagazine.Models.Entity;
|
||||||
@ -939,7 +940,7 @@ public class UserAnswerTaskService(
|
|||||||
|
|
||||||
if (relatedTasks == null || relatedTasks.Count == 0)
|
if (relatedTasks == null || relatedTasks.Count == 0)
|
||||||
{
|
{
|
||||||
throw new BusinessException("任务不存在", 404);
|
throw new BusinessException("任务不存在", ResultCode.NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================
|
// ============================================
|
||||||
@ -972,7 +973,7 @@ public class UserAnswerTaskService(
|
|||||||
|
|
||||||
if (userAnswers == null || userAnswers.Count == 0)
|
if (userAnswers == null || userAnswers.Count == 0)
|
||||||
{
|
{
|
||||||
throw new BusinessException("请先完成答题再领取积分", 400);
|
throw new BusinessException("请先完成答题再领取积分", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================
|
// ============================================
|
||||||
@ -988,7 +989,7 @@ public class UserAnswerTaskService(
|
|||||||
var completedAnswer = userAnswers.FirstOrDefault(a => a.JournalPageTaskId == task.Id && a.Status == (int)UserAnswerStatusEnum.Complete);
|
var completedAnswer = userAnswers.FirstOrDefault(a => a.JournalPageTaskId == task.Id && a.Status == (int)UserAnswerStatusEnum.Complete);
|
||||||
if (completedAnswer == null)
|
if (completedAnswer == null)
|
||||||
{
|
{
|
||||||
throw new BusinessException("跨页题目需要完成所有任务才能领取积分", 400);
|
throw new BusinessException("跨页题目需要完成所有任务才能领取积分", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -997,7 +998,7 @@ public class UserAnswerTaskService(
|
|||||||
// 普通题目:只需要 Status=1 即可
|
// 普通题目:只需要 Status=1 即可
|
||||||
if (userAnswers.FirstOrDefault()?.Status != (int)UserAnswerStatusEnum.Complete)
|
if (userAnswers.FirstOrDefault()?.Status != (int)UserAnswerStatusEnum.Complete)
|
||||||
{
|
{
|
||||||
throw new BusinessException("请先完成答题再领取积分", 400);
|
throw new BusinessException("请先完成答题再领取积分", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1020,7 +1021,7 @@ public class UserAnswerTaskService(
|
|||||||
|
|
||||||
if (totalPoints <= 0)
|
if (totalPoints <= 0)
|
||||||
{
|
{
|
||||||
throw new BusinessException("该任务无积分可领取", 400);
|
throw new BusinessException("该任务无积分可领取", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================
|
// ============================================
|
||||||
@ -1054,7 +1055,7 @@ public class UserAnswerTaskService(
|
|||||||
|
|
||||||
if (existingRecord != null)
|
if (existingRecord != null)
|
||||||
{
|
{
|
||||||
throw new BusinessException("积分已领取,请勿重复领取", 400);
|
throw new BusinessException("积分已领取,请勿重复领取", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================
|
// ============================================
|
||||||
@ -1110,7 +1111,7 @@ public class UserAnswerTaskService(
|
|||||||
|
|
||||||
if (input == null || input.GroupIds == null || input.GroupIds.Count == 0)
|
if (input == null || input.GroupIds == null || input.GroupIds.Count == 0)
|
||||||
{
|
{
|
||||||
throw new BusinessException("任务分组Id列表不能为空", 400);
|
throw new BusinessException("任务分组Id列表不能为空", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
var groupIds = input.GroupIds.Distinct().ToList();
|
var groupIds = input.GroupIds.Distinct().ToList();
|
||||||
|
|||||||
@ -31,14 +31,14 @@ public class UserJournalService(
|
|||||||
// 校验参数
|
// 校验参数
|
||||||
if (input.JournalId <= 0|| input.Id <= 0)
|
if (input.JournalId <= 0|| input.Id <= 0)
|
||||||
{
|
{
|
||||||
throw new BusinessException("参数错误,未获取到期刊", 400);
|
throw new BusinessException("参数错误,未获取到期刊", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
// 校验用户是否存在
|
// 校验用户是否存在
|
||||||
var user = await usersRepository.GetByIdAsync(userId);
|
var user = await usersRepository.GetByIdAsync(userId);
|
||||||
if (user == null || user.IsDeleted)
|
if (user == null || user.IsDeleted)
|
||||||
{
|
{
|
||||||
logger.LogWarning("绑定期刊失败,用户不存在,UserId: {UserId}", userId);
|
logger.LogWarning("绑定期刊失败,用户不存在,UserId: {UserId}", userId);
|
||||||
throw new BusinessException("用户不存在", 404);
|
throw new BusinessException("用户不存在", ResultCode.NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 校验期刊是否存在
|
// 校验期刊是否存在
|
||||||
@ -46,14 +46,14 @@ public class UserJournalService(
|
|||||||
if (journal == null || journal.IsDeleted)
|
if (journal == null || journal.IsDeleted)
|
||||||
{
|
{
|
||||||
logger.LogWarning("绑定期刊失败,期刊不存在,JournalId: {JournalId}", input.JournalId);
|
logger.LogWarning("绑定期刊失败,期刊不存在,JournalId: {JournalId}", input.JournalId);
|
||||||
throw new BusinessException("期刊不存在", 404);
|
throw new BusinessException("期刊不存在", ResultCode.NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 校验期刊状态
|
// 校验期刊状态
|
||||||
if (journal.Status != (int)JournalStatusEnum.Published)
|
if (journal.Status != (int)JournalStatusEnum.Published)
|
||||||
{
|
{
|
||||||
logger.LogWarning("绑定期刊失败,期刊未发布,JournalId: {JournalId}, Status: {Status}", input.JournalId, journal.Status);
|
logger.LogWarning("绑定期刊失败,期刊未发布,JournalId: {JournalId}, Status: {Status}", input.JournalId, journal.Status);
|
||||||
throw new BusinessException("该期刊暂未发布,无法绑定", 400);
|
throw new BusinessException("该期刊暂未发布,无法绑定", ResultCode.UNPROCESSABLE_ENTITY);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 防重复绑定:同一用户 + 期刊 + 实例 + 类型
|
// 防重复绑定:同一用户 + 期刊 + 实例 + 类型
|
||||||
@ -63,7 +63,7 @@ public class UserJournalService(
|
|||||||
if (isExist)
|
if (isExist)
|
||||||
{
|
{
|
||||||
logger.LogWarning("重复绑定期刊,UserId: {UserId}, JournalId: {JournalId}, Type: {Type}", userId, input.JournalId, input.Type);
|
logger.LogWarning("重复绑定期刊,UserId: {UserId}, JournalId: {JournalId}, Type: {Type}", userId, input.JournalId, input.Type);
|
||||||
throw new BusinessException("该期刊已被绑定", 400);
|
throw new BusinessException("该期刊已被绑定", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查是否为首次绑定期刊(用于激活宠物)
|
// 检查是否为首次绑定期刊(用于激活宠物)
|
||||||
@ -89,7 +89,7 @@ public class UserJournalService(
|
|||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
logger.LogError("绑定期刊失败,写入数据库失败,UserId: {UserId}, JournalId: {JournalId}", userId, input.JournalId);
|
logger.LogError("绑定期刊失败,写入数据库失败,UserId: {UserId}, JournalId: {JournalId}", userId, input.JournalId);
|
||||||
throw new BusinessException("绑定期刊失败,请稍后重试", 500);
|
throw new BusinessException("绑定期刊失败,请稍后重试", ResultCode.GLOBAL_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.LogInformation("用户绑定期刊成功,UserId: {UserId}, JournalId: {JournalId}, Id: {Id}", userId, input.JournalId, userJournal.Id);
|
logger.LogInformation("用户绑定期刊成功,UserId: {UserId}, JournalId: {JournalId}, Id: {Id}", userId, input.JournalId, userJournal.Id);
|
||||||
@ -129,12 +129,12 @@ public class UserJournalService(
|
|||||||
|
|
||||||
if (input.PageIndex <= 0)
|
if (input.PageIndex <= 0)
|
||||||
{
|
{
|
||||||
throw new BusinessException("页码必须大于0", 400);
|
throw new BusinessException("页码必须大于0", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input.PageSize <= 0 || input.PageSize > 100)
|
if (input.PageSize <= 0 || input.PageSize > 100)
|
||||||
{
|
{
|
||||||
throw new BusinessException("每页条数必须在1-100之间", 400);
|
throw new BusinessException("每页条数必须在1-100之间", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
RefAsync<int> totalNumber = 0;
|
RefAsync<int> totalNumber = 0;
|
||||||
@ -167,21 +167,21 @@ public class UserJournalService(
|
|||||||
if (userJournal == null || userJournal.IsDeleted)
|
if (userJournal == null || userJournal.IsDeleted)
|
||||||
{
|
{
|
||||||
logger.LogWarning("取消绑定失败,记录不存在,Id: {Id}", id);
|
logger.LogWarning("取消绑定失败,记录不存在,Id: {Id}", id);
|
||||||
throw new BusinessException("绑定记录不存在", 404);
|
throw new BusinessException("绑定记录不存在", ResultCode.NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 校验归属权:只能取消自己的绑定
|
// 校验归属权:只能取消自己的绑定
|
||||||
if (userJournal.UserId != userId)
|
if (userJournal.UserId != userId)
|
||||||
{
|
{
|
||||||
logger.LogWarning("取消绑定失败,无权操作,UserId: {UserId}, RecordUserId: {RecordUserId}", userId, userJournal.UserId);
|
logger.LogWarning("取消绑定失败,无权操作,UserId: {UserId}, RecordUserId: {RecordUserId}", userId, userJournal.UserId);
|
||||||
throw new BusinessException("无权取消该绑定", 403);
|
throw new BusinessException("无权取消该绑定", ResultCode.FORBIDDEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = await userJournalRepository.DeleteByIdAsync(id);
|
var result = await userJournalRepository.DeleteByIdAsync(id);
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
logger.LogError("取消绑定失败,Id: {Id}", id);
|
logger.LogError("取消绑定失败,Id: {Id}", id);
|
||||||
throw new BusinessException("取消绑定失败,请稍后重试", 500);
|
throw new BusinessException("取消绑定失败,请稍后重试", ResultCode.GLOBAL_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.LogInformation("取消期刊绑定成功,UserId: {UserId}, Id: {Id}", userId, id);
|
logger.LogInformation("取消期刊绑定成功,UserId: {UserId}, Id: {Id}", userId, id);
|
||||||
|
|||||||
@ -197,7 +197,7 @@ public class UsersService(
|
|||||||
// 校验用户是否存在
|
// 校验用户是否存在
|
||||||
var user = await Queryable().Where(u => u.Id == userId && !u.IsDeleted).FirstAsync();
|
var user = await Queryable().Where(u => u.Id == userId && !u.IsDeleted).FirstAsync();
|
||||||
if (user == null)
|
if (user == null)
|
||||||
throw new BusinessException("用户不存在", 404);
|
throw new BusinessException("用户不存在", ResultCode.NOT_FOUND);
|
||||||
|
|
||||||
// 调用积分服务增加积分
|
// 调用积分服务增加积分
|
||||||
var result = await pointsService.AddPointsAsync(new AddPointsInput
|
var result = await pointsService.AddPointsAsync(new AddPointsInput
|
||||||
@ -247,7 +247,7 @@ public class UsersService(
|
|||||||
// 校验用户是否存在
|
// 校验用户是否存在
|
||||||
var user = await Queryable().Where(u => u.Id == userId && !u.IsDeleted).FirstAsync();
|
var user = await Queryable().Where(u => u.Id == userId && !u.IsDeleted).FirstAsync();
|
||||||
if (user == null)
|
if (user == null)
|
||||||
throw new BusinessException("用户不存在", 404);
|
throw new BusinessException("用户不存在", ResultCode.NOT_FOUND);
|
||||||
|
|
||||||
// 调用积分服务扣除积分
|
// 调用积分服务扣除积分
|
||||||
var result = await pointsService.DeductPointsAsync(new DeductPointsInput
|
var result = await pointsService.DeductPointsAsync(new DeductPointsInput
|
||||||
|
|||||||
@ -4,6 +4,7 @@ using QYZH.InteractiveMagazine.Common.Helpers;
|
|||||||
using QYZH.InteractiveMagazine.Infrastructure.Auth;
|
using QYZH.InteractiveMagazine.Infrastructure.Auth;
|
||||||
using QYZH.InteractiveMagazine.IService;
|
using QYZH.InteractiveMagazine.IService;
|
||||||
using QYZH.InteractiveMagazine.Models.Common;
|
using QYZH.InteractiveMagazine.Models.Common;
|
||||||
|
using QYZH.InteractiveMagazine.Models.Dto;
|
||||||
using QYZH.InteractiveMagazine.Models.Entity;
|
using QYZH.InteractiveMagazine.Models.Entity;
|
||||||
using QYZH.InteractiveMagazine.Models.Enum;
|
using QYZH.InteractiveMagazine.Models.Enum;
|
||||||
using QYZH.InteractiveMagazine.Models.Settings;
|
using QYZH.InteractiveMagazine.Models.Settings;
|
||||||
@ -38,7 +39,7 @@ public class WeChatAuthService(
|
|||||||
logger.LogInformation("微信小程序登录");
|
logger.LogInformation("微信小程序登录");
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(input.Code))
|
if (string.IsNullOrWhiteSpace(input.Code))
|
||||||
throw new BusinessException("微信登录凭证 code 不能为空", 400);
|
throw new BusinessException("微信登录凭证 code 不能为空", ResultCode.BAD_REQUEST);
|
||||||
|
|
||||||
var weChatSettings = GetWeChatSettings();
|
var weChatSettings = GetWeChatSettings();
|
||||||
|
|
||||||
@ -48,7 +49,7 @@ public class WeChatAuthService(
|
|||||||
{
|
{
|
||||||
var errMsg = wxResponse?.ErrMsg ?? "未知错误";
|
var errMsg = wxResponse?.ErrMsg ?? "未知错误";
|
||||||
logger.LogWarning("微信 code2session 接口调用失败,errcode: {ErrCode}, errmsg: {ErrMsg}", wxResponse?.ErrCode, errMsg);
|
logger.LogWarning("微信 code2session 接口调用失败,errcode: {ErrCode}, errmsg: {ErrMsg}", wxResponse?.ErrCode, errMsg);
|
||||||
throw new BusinessException($"微信登录失败:{errMsg}", 400);
|
throw new BusinessException($"微信登录失败:{errMsg}", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.LogInformation("微信 code2session 成功,OpenId: {OpenId}", wxResponse.OpenId);
|
logger.LogInformation("微信 code2session 成功,OpenId: {OpenId}", wxResponse.OpenId);
|
||||||
@ -130,7 +131,7 @@ public class WeChatAuthService(
|
|||||||
logger.LogInformation("微信快捷登录,OpenId: {OpenId}", input.OpenId);
|
logger.LogInformation("微信快捷登录,OpenId: {OpenId}", input.OpenId);
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(input.OpenId))
|
if (string.IsNullOrWhiteSpace(input.OpenId))
|
||||||
throw new BusinessException("OpenId 不能为空", 400);
|
throw new BusinessException("OpenId 不能为空", ResultCode.BAD_REQUEST);
|
||||||
|
|
||||||
var wxUser = await wxUserRepository.Context.Queryable<WxUser>()
|
var wxUser = await wxUserRepository.Context.Queryable<WxUser>()
|
||||||
.Where(w => w.OpenId == input.OpenId && !w.IsDeleted)
|
.Where(w => w.OpenId == input.OpenId && !w.IsDeleted)
|
||||||
@ -139,7 +140,7 @@ public class WeChatAuthService(
|
|||||||
if (wxUser == null)
|
if (wxUser == null)
|
||||||
{
|
{
|
||||||
logger.LogWarning("快捷登录失败,OpenId: {OpenId} 下无 WxUser", input.OpenId);
|
logger.LogWarning("快捷登录失败,OpenId: {OpenId} 下无 WxUser", input.OpenId);
|
||||||
throw new BusinessException("未找到该微信账号关联的用户,请先完成注册", 404);
|
throw new BusinessException("未找到该微信账号关联的用户,请先完成注册", ResultCode.NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
var users = await wxUserRepository.Context.Queryable<Users>()
|
var users = await wxUserRepository.Context.Queryable<Users>()
|
||||||
@ -165,17 +166,17 @@ public class WeChatAuthService(
|
|||||||
.FirstAsync();
|
.FirstAsync();
|
||||||
|
|
||||||
if (targetUser == null)
|
if (targetUser == null)
|
||||||
throw new BusinessException("目标用户不存在", 404);
|
throw new BusinessException("目标用户不存在", ResultCode.NOT_FOUND);
|
||||||
|
|
||||||
// 校验目标用户属于同一 WxUser
|
// 校验目标用户属于同一 WxUser
|
||||||
if (targetUser.WxUserId != wxUserId)
|
if (targetUser.WxUserId != wxUserId)
|
||||||
{
|
{
|
||||||
logger.LogWarning("切换用户失败,WxUserId 不匹配,当前: {Current}, 目标: {Target}", wxUserId, targetUser.WxUserId);
|
logger.LogWarning("切换用户失败,WxUserId 不匹配,当前: {Current}, 目标: {Target}", wxUserId, targetUser.WxUserId);
|
||||||
throw new BusinessException("无法切换到该用户", 403);
|
throw new BusinessException("无法切换到该用户", ResultCode.FORBIDDEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (targetUser.Status == (int)UserStatusEnum.Disabled)
|
if (targetUser.Status == (int)UserStatusEnum.Disabled)
|
||||||
throw new BusinessException("目标账号已被禁用", 403);
|
throw new BusinessException("目标账号已被禁用", ResultCode.FORBIDDEN);
|
||||||
|
|
||||||
// 更新 IsLastOnline(清除所有,设置目标为 true)
|
// 更新 IsLastOnline(清除所有,设置目标为 true)
|
||||||
await wxUserRepository.Context.Updateable<Users>()
|
await wxUserRepository.Context.Updateable<Users>()
|
||||||
@ -232,7 +233,7 @@ public class WeChatAuthService(
|
|||||||
logger.LogInformation("新增用户,WxUserId: {WxUserId}, Name: {Name}", wxUserId, input.Name);
|
logger.LogInformation("新增用户,WxUserId: {WxUserId}, Name: {Name}", wxUserId, input.Name);
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(input.Name))
|
if (string.IsNullOrWhiteSpace(input.Name))
|
||||||
throw new BusinessException("昵称不能为空", 400);
|
throw new BusinessException("昵称不能为空", ResultCode.BAD_REQUEST);
|
||||||
|
|
||||||
// 校验 WxUser 是否存在
|
// 校验 WxUser 是否存在
|
||||||
var wxUser = await wxUserRepository.Context.Queryable<WxUser>()
|
var wxUser = await wxUserRepository.Context.Queryable<WxUser>()
|
||||||
@ -240,7 +241,7 @@ public class WeChatAuthService(
|
|||||||
.FirstAsync();
|
.FirstAsync();
|
||||||
|
|
||||||
if (wxUser == null)
|
if (wxUser == null)
|
||||||
throw new BusinessException("微信用户不存在", 404);
|
throw new BusinessException("微信用户不存在", ResultCode.NOT_FOUND);
|
||||||
|
|
||||||
// 创建新用户
|
// 创建新用户
|
||||||
var newUser = new Users
|
var newUser = new Users
|
||||||
@ -280,14 +281,14 @@ public class WeChatAuthService(
|
|||||||
logger.LogInformation("修改家长名字,WxUserId: {WxUserId}, NewName: {Name}", wxUserId, input.Name);
|
logger.LogInformation("修改家长名字,WxUserId: {WxUserId}, NewName: {Name}", wxUserId, input.Name);
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(input.Name))
|
if (string.IsNullOrWhiteSpace(input.Name))
|
||||||
throw new BusinessException("名字不能为空", 400);
|
throw new BusinessException("名字不能为空", ResultCode.BAD_REQUEST);
|
||||||
|
|
||||||
var wxUser = await wxUserRepository.Context.Queryable<WxUser>()
|
var wxUser = await wxUserRepository.Context.Queryable<WxUser>()
|
||||||
.Where(w => w.Id == wxUserId && !w.IsDeleted)
|
.Where(w => w.Id == wxUserId && !w.IsDeleted)
|
||||||
.FirstAsync();
|
.FirstAsync();
|
||||||
|
|
||||||
if (wxUser == null)
|
if (wxUser == null)
|
||||||
throw new BusinessException("微信用户不存在", 404);
|
throw new BusinessException("微信用户不存在", ResultCode.NOT_FOUND);
|
||||||
|
|
||||||
await wxUserRepository.Context.Updateable<WxUser>()
|
await wxUserRepository.Context.Updateable<WxUser>()
|
||||||
.SetColumns(w => w.Name == input.Name.Trim())
|
.SetColumns(w => w.Name == input.Name.Trim())
|
||||||
@ -358,7 +359,7 @@ public class WeChatAuthService(
|
|||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.LogError(ex, "调用微信 code2session 接口异常,URL: {Url}", url);
|
logger.LogError(ex, "调用微信 code2session 接口异常,URL: {Url}", url);
|
||||||
throw new BusinessException("微信服务请求失败,请稍后重试", 500);
|
throw new BusinessException("微信服务请求失败,请稍后重试", ResultCode.GLOBAL_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -378,7 +379,7 @@ public class WeChatAuthService(
|
|||||||
{
|
{
|
||||||
var errMsg = response?.ErrMsg ?? "未知错误";
|
var errMsg = response?.ErrMsg ?? "未知错误";
|
||||||
logger.LogError("获取微信 access_token 失败,errcode: {ErrCode}, errmsg: {ErrMsg}", response?.ErrCode, errMsg);
|
logger.LogError("获取微信 access_token 失败,errcode: {ErrCode}, errmsg: {ErrMsg}", response?.ErrCode, errMsg);
|
||||||
throw new BusinessException("微信服务请求失败,请稍后重试", 500);
|
throw new BusinessException("微信服务请求失败,请稍后重试", ResultCode.GLOBAL_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
var expiresIn = response.ExpiresIn > 300 ? response.ExpiresIn - 300 : response.ExpiresIn;
|
var expiresIn = response.ExpiresIn > 300 ? response.ExpiresIn - 300 : response.ExpiresIn;
|
||||||
@ -441,7 +442,7 @@ public class WeChatAuthService(
|
|||||||
if (settings == null || string.IsNullOrWhiteSpace(settings.AppId) || string.IsNullOrWhiteSpace(settings.AppSecret))
|
if (settings == null || string.IsNullOrWhiteSpace(settings.AppId) || string.IsNullOrWhiteSpace(settings.AppSecret))
|
||||||
{
|
{
|
||||||
logger.LogError("微信配置不完整,请检查 appsettings.json 中的 WeChatSettings 节点");
|
logger.LogError("微信配置不完整,请检查 appsettings.json 中的 WeChatSettings 节点");
|
||||||
throw new BusinessException("微信配置不完整,请联系系统管理员", 500);
|
throw new BusinessException("微信配置不完整,请联系系统管理员", ResultCode.GLOBAL_ERROR);
|
||||||
}
|
}
|
||||||
return settings;
|
return settings;
|
||||||
}
|
}
|
||||||
@ -458,7 +459,7 @@ public class WeChatAuthService(
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(jwtSettings.SecretKey))
|
if (string.IsNullOrWhiteSpace(jwtSettings.SecretKey))
|
||||||
throw new BusinessException("JWT 配置不完整", 500);
|
throw new BusinessException("JWT 配置不完整", ResultCode.GLOBAL_ERROR);
|
||||||
|
|
||||||
return jwtSettings;
|
return jwtSettings;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -116,13 +116,13 @@ public class WeChatCommunityService(
|
|||||||
|
|
||||||
if (input.MessageId <= 0)
|
if (input.MessageId <= 0)
|
||||||
{
|
{
|
||||||
throw new BusinessException("消息ID无效", 400);
|
throw new BusinessException("消息ID无效", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
var message = await messageRepository.GetByIdAsync(input.MessageId);
|
var message = await messageRepository.GetByIdAsync(input.MessageId);
|
||||||
if (message == null)
|
if (message == null)
|
||||||
{
|
{
|
||||||
throw new BusinessException("消息不存在", 404);
|
throw new BusinessException("消息不存在", ResultCode.NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查是否已点赞
|
// 检查是否已点赞
|
||||||
@ -132,7 +132,7 @@ public class WeChatCommunityService(
|
|||||||
|
|
||||||
if (existingLike != null)
|
if (existingLike != null)
|
||||||
{
|
{
|
||||||
throw new BusinessException("您已点赞过该消息", 400);
|
throw new BusinessException("您已点赞过该消息", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 插入点赞记录
|
// 插入点赞记录
|
||||||
@ -151,7 +151,7 @@ public class WeChatCommunityService(
|
|||||||
var insertResult = await Context.Insertable(like).ExecuteCommandAsync();
|
var insertResult = await Context.Insertable(like).ExecuteCommandAsync();
|
||||||
if (insertResult <= 0)
|
if (insertResult <= 0)
|
||||||
{
|
{
|
||||||
throw new BusinessException("点赞失败", 500);
|
throw new BusinessException("点赞失败", ResultCode.GLOBAL_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新点赞数
|
// 更新点赞数
|
||||||
@ -183,13 +183,13 @@ public class WeChatCommunityService(
|
|||||||
|
|
||||||
if (messageId <= 0)
|
if (messageId <= 0)
|
||||||
{
|
{
|
||||||
throw new BusinessException("消息ID无效", 400);
|
throw new BusinessException("消息ID无效", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
var message = await messageRepository.GetByIdAsync(messageId);
|
var message = await messageRepository.GetByIdAsync(messageId);
|
||||||
if (message == null)
|
if (message == null)
|
||||||
{
|
{
|
||||||
throw new BusinessException("消息不存在", 404);
|
throw new BusinessException("消息不存在", ResultCode.NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
var existingLike = await Context.Queryable<CommunityMessageLike>()
|
var existingLike = await Context.Queryable<CommunityMessageLike>()
|
||||||
@ -198,7 +198,7 @@ public class WeChatCommunityService(
|
|||||||
|
|
||||||
if (existingLike == null)
|
if (existingLike == null)
|
||||||
{
|
{
|
||||||
throw new BusinessException("您尚未点赞过该消息", 400);
|
throw new BusinessException("您尚未点赞过该消息", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 软删除点赞记录
|
// 软删除点赞记录
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using QYZH.InteractiveMagazine.IService;
|
using QYZH.InteractiveMagazine.IService;
|
||||||
using QYZH.InteractiveMagazine.Models.Common;
|
using QYZH.InteractiveMagazine.Models.Common;
|
||||||
|
using QYZH.InteractiveMagazine.Models.Dto;
|
||||||
using QYZH.InteractiveMagazine.Models.Dto.Bag;
|
using QYZH.InteractiveMagazine.Models.Dto.Bag;
|
||||||
using QYZH.InteractiveMagazine.Models.Dto.Mall;
|
using QYZH.InteractiveMagazine.Models.Dto.Mall;
|
||||||
using QYZH.InteractiveMagazine.Models.Dto.Points;
|
using QYZH.InteractiveMagazine.Models.Dto.Points;
|
||||||
@ -187,10 +188,10 @@ public class WxMallService(
|
|||||||
userId, input.ProductId, input.Quantity);
|
userId, input.ProductId, input.Quantity);
|
||||||
|
|
||||||
if (input.ProductId <= 0)
|
if (input.ProductId <= 0)
|
||||||
throw new BusinessException("商品Id无效", 400);
|
throw new BusinessException("商品Id无效", ResultCode.BAD_REQUEST);
|
||||||
|
|
||||||
if (input.Quantity <= 0)
|
if (input.Quantity <= 0)
|
||||||
throw new BusinessException("兑换数量必须大于0", 400);
|
throw new BusinessException("兑换数量必须大于0", ResultCode.BAD_REQUEST);
|
||||||
|
|
||||||
// 查询商品
|
// 查询商品
|
||||||
var product = await exchangeRecordRepository.Context.Queryable<Product>()
|
var product = await exchangeRecordRepository.Context.Queryable<Product>()
|
||||||
@ -198,7 +199,7 @@ public class WxMallService(
|
|||||||
.FirstAsync();
|
.FirstAsync();
|
||||||
|
|
||||||
if (product == null)
|
if (product == null)
|
||||||
throw new BusinessException("商品不存在或已下架", 404);
|
throw new BusinessException("商品不存在或已下架", ResultCode.NOT_FOUND);
|
||||||
|
|
||||||
var totalCost = product.Price * input.Quantity;
|
var totalCost = product.Price * input.Quantity;
|
||||||
|
|
||||||
@ -404,24 +405,24 @@ public class WxMallService(
|
|||||||
logger.LogInformation("使用背包物品,UserId: {UserId}, BagItemId: {BagItemId}", userId, input.BagItemId);
|
logger.LogInformation("使用背包物品,UserId: {UserId}, BagItemId: {BagItemId}", userId, input.BagItemId);
|
||||||
|
|
||||||
if (input.BagItemId <= 0)
|
if (input.BagItemId <= 0)
|
||||||
throw new BusinessException("背包物品Id无效", 400);
|
throw new BusinessException("背包物品Id无效", ResultCode.BAD_REQUEST);
|
||||||
|
|
||||||
var bagItem = await exchangeRecordRepository.Context.Queryable<UserBag>()
|
var bagItem = await exchangeRecordRepository.Context.Queryable<UserBag>()
|
||||||
.Where(b => b.Id == input.BagItemId && b.UserId == userId && b.Status == (int)UserBagStatusEnum.Available)
|
.Where(b => b.Id == input.BagItemId && b.UserId == userId && b.Status == (int)UserBagStatusEnum.Available)
|
||||||
.FirstAsync();
|
.FirstAsync();
|
||||||
|
|
||||||
if (bagItem == null)
|
if (bagItem == null)
|
||||||
throw new BusinessException("背包物品不存在", 404);
|
throw new BusinessException("背包物品不存在", ResultCode.NOT_FOUND);
|
||||||
|
|
||||||
if (bagItem.Quantity <= 0)
|
if (bagItem.Quantity <= 0)
|
||||||
throw new BusinessException("物品数量不足", 400);
|
throw new BusinessException("物品数量不足", ResultCode.BAD_REQUEST);
|
||||||
|
|
||||||
switch (bagItem.ItemType)
|
switch (bagItem.ItemType)
|
||||||
{
|
{
|
||||||
case "MakeUpCard":
|
case "MakeUpCard":
|
||||||
return await UseMakeUpCardAsync(userId, bagItem, input);
|
return await UseMakeUpCardAsync(userId, bagItem, input);
|
||||||
default:
|
default:
|
||||||
throw new BusinessException($"不支持使用该类型物品: {bagItem.ItemType}", 400);
|
throw new BusinessException($"不支持使用该类型物品: {bagItem.ItemType}", ResultCode.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -431,15 +432,15 @@ public class WxMallService(
|
|||||||
private async Task<UseItemOutput> UseMakeUpCardAsync(long userId, UserBag bagItem, UseItemInput input)
|
private async Task<UseItemOutput> UseMakeUpCardAsync(long userId, UserBag bagItem, UseItemInput input)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(input.TargetDate))
|
if (string.IsNullOrEmpty(input.TargetDate))
|
||||||
throw new BusinessException("请指定补签日期", 400);
|
throw new BusinessException("请指定补签日期", ResultCode.BAD_REQUEST);
|
||||||
|
|
||||||
if (!DateTime.TryParse(input.TargetDate, out var targetDate))
|
if (!DateTime.TryParse(input.TargetDate, out var targetDate))
|
||||||
throw new BusinessException("日期格式无效", 400);
|
throw new BusinessException("日期格式无效", ResultCode.BAD_REQUEST);
|
||||||
|
|
||||||
targetDate = targetDate.Date;
|
targetDate = targetDate.Date;
|
||||||
|
|
||||||
if (targetDate >= DateTime.Now.Date)
|
if (targetDate >= DateTime.Now.Date)
|
||||||
throw new BusinessException("只能补签过去的日期", 400);
|
throw new BusinessException("只能补签过去的日期", ResultCode.BAD_REQUEST);
|
||||||
|
|
||||||
// 调用签到服务执行补签(内部会检查并扣减补签卡)
|
// 调用签到服务执行补签(内部会检查并扣减补签卡)
|
||||||
var checkInResult = await checkInService.MakeUpCheckInAsync(userId, targetDate);
|
var checkInResult = await checkInService.MakeUpCheckInAsync(userId, targetDate);
|
||||||
@ -467,7 +468,7 @@ public class WxMallService(
|
|||||||
.FirstAsync();
|
.FirstAsync();
|
||||||
|
|
||||||
if (pet == null)
|
if (pet == null)
|
||||||
throw new BusinessException("您还没有宠物", 404);
|
throw new BusinessException("您还没有宠物", ResultCode.NOT_FOUND);
|
||||||
|
|
||||||
if (input.SkinId == 0)
|
if (input.SkinId == 0)
|
||||||
{
|
{
|
||||||
@ -488,7 +489,7 @@ public class WxMallService(
|
|||||||
.FirstAsync();
|
.FirstAsync();
|
||||||
|
|
||||||
if (skin == null)
|
if (skin == null)
|
||||||
throw new BusinessException("皮肤不存在", 404);
|
throw new BusinessException("皮肤不存在", ResultCode.NOT_FOUND);
|
||||||
|
|
||||||
// 校验背包中是否拥有该皮肤(通过 MetaData 中的 SkinId 判断)
|
// 校验背包中是否拥有该皮肤(通过 MetaData 中的 SkinId 判断)
|
||||||
var hasSkin = await exchangeRecordRepository.Context.Queryable<UserBag>()
|
var hasSkin = await exchangeRecordRepository.Context.Queryable<UserBag>()
|
||||||
@ -499,7 +500,7 @@ public class WxMallService(
|
|||||||
var owned = hasSkin.Any(b => GetSkinIdFromMetaData(b.MetaData) == input.SkinId);
|
var owned = hasSkin.Any(b => GetSkinIdFromMetaData(b.MetaData) == input.SkinId);
|
||||||
|
|
||||||
if (!owned)
|
if (!owned)
|
||||||
throw new BusinessException("您尚未拥有该皮肤,请先兑换", 400);
|
throw new BusinessException("您尚未拥有该皮肤,请先兑换", ResultCode.BAD_REQUEST);
|
||||||
|
|
||||||
// 换肤
|
// 换肤
|
||||||
await exchangeRecordRepository.Context.Updateable<UserPet>()
|
await exchangeRecordRepository.Context.Updateable<UserPet>()
|
||||||
|
|||||||
@ -62,7 +62,10 @@ public abstract class BaseController : ControllerBase
|
|||||||
/// <returns>统一响应对象</returns>
|
/// <returns>统一响应对象</returns>
|
||||||
protected BaseResponse<object> Fail(string message, int code = 500)
|
protected BaseResponse<object> Fail(string message, int code = 500)
|
||||||
{
|
{
|
||||||
return BaseResponse<object>.Fail(ResultCode.GLOBAL_ERROR, message);
|
var resultCode = Enum.IsDefined(typeof(ResultCode), code)
|
||||||
|
? (ResultCode)code
|
||||||
|
: ResultCode.GLOBAL_ERROR;
|
||||||
|
return BaseResponse<object>.Fail(resultCode, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected IActionResult ApiResult(bool success, string msg)
|
protected IActionResult ApiResult(bool success, string msg)
|
||||||
@ -91,7 +94,7 @@ public abstract class BaseController : ControllerBase
|
|||||||
//var webHostEnvironment = App.WebHostEnvironment;
|
//var webHostEnvironment = App.WebHostEnvironment;
|
||||||
if (!Path.Exists(path))
|
if (!Path.Exists(path))
|
||||||
{
|
{
|
||||||
throw new BusinessException(fileName + "文件不存在");
|
throw new BusinessException(fileName + "文件不存在", ResultCode.NOT_FOUND);
|
||||||
}
|
}
|
||||||
var stream = System.IO.File.OpenRead(path); //创建文件流
|
var stream = System.IO.File.OpenRead(path); //创建文件流
|
||||||
|
|
||||||
|
|||||||
@ -395,15 +395,15 @@ namespace QYZH.InteractiveMagazine.WebApi.Controllers
|
|||||||
{
|
{
|
||||||
var entity = await JournalService.GetFirstAsync(x => x.Id == JournalId);
|
var entity = await JournalService.GetFirstAsync(x => x.Id == JournalId);
|
||||||
if (entity == null)
|
if (entity == null)
|
||||||
throw new BusinessException("书籍不存在");
|
throw new BusinessException("书籍不存在", ResultCode.NOT_FOUND);
|
||||||
|
|
||||||
var downloadUrl = entity.DownloadJournalPagePdfName;
|
var downloadUrl = entity.DownloadJournalPagePdfName;
|
||||||
if (string.IsNullOrWhiteSpace(downloadUrl))
|
if (string.IsNullOrWhiteSpace(downloadUrl))
|
||||||
throw new BusinessException("下载点阵码PDF文件为空,请先铺码");
|
throw new BusinessException("下载点阵码PDF文件为空,请先铺码", ResultCode.BAD_REQUEST);
|
||||||
|
|
||||||
var stream = await httpClientFactory.CreateClient().GetStreamAsync(downloadUrl); //创建文件流
|
var stream = await httpClientFactory.CreateClient().GetStreamAsync(downloadUrl); //创建文件流
|
||||||
if (stream == null)
|
if (stream == null)
|
||||||
throw new BusinessException("下载点阵码PDF文件失败");
|
throw new BusinessException("下载点阵码PDF文件失败", ResultCode.GLOBAL_ERROR);
|
||||||
|
|
||||||
Response.Headers.Append("Access-Control-Expose-Headers", "Content-Disposition");
|
Response.Headers.Append("Access-Control-Expose-Headers", "Content-Disposition");
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
using QYZH.InteractiveMagazine.Common.Extensions;
|
||||||
using QYZH.InteractiveMagazine.Infrastructure.OSS;
|
using QYZH.InteractiveMagazine.Infrastructure.OSS;
|
||||||
using QYZH.InteractiveMagazine.Models.Dto.Journal;
|
using QYZH.InteractiveMagazine.Models.Dto.Journal;
|
||||||
using QYZH.InteractiveMagazine.Models.Entity;
|
using QYZH.InteractiveMagazine.Models.Entity;
|
||||||
@ -65,7 +66,19 @@ public class AutoDotCodeConsumer(IConfiguration configuration,
|
|||||||
var uploadFilePath = uploadPdfDic + uploadFileName;
|
var uploadFilePath = uploadPdfDic + uploadFileName;
|
||||||
|
|
||||||
// 获取上传成功的书籍页码pdf文件
|
// 获取上传成功的书籍页码pdf文件
|
||||||
var pdfSteam = await httpClientFactory.CreateClient().GetStreamAsync(journalPagePrintDtoMessage.JournalPdfUrl, cancellationToken);
|
var journalPdfKey = journalPagePrintDtoMessage.JournalPdfUrl?.RemoveDomain();
|
||||||
|
if (string.IsNullOrWhiteSpace(journalPdfKey))
|
||||||
|
{
|
||||||
|
logger.LogError("书籍上传的PDF文件地址为空,JournalId: {JournalId}", journalPagePrintDtoMessage.JournalId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await using var pdfSteam = ossService.GetObjectStream(journalPdfKey);
|
||||||
|
if (pdfSteam == null)
|
||||||
|
{
|
||||||
|
logger.LogError("获取书籍上传的PDF文件失败,OSS Key: {OssKey}", journalPdfKey);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
await using (var fs = new FileStream(uploadFilePath, FileMode.CreateNew, FileAccess.Write))
|
await using (var fs = new FileStream(uploadFilePath, FileMode.CreateNew, FileAccess.Write))
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,18 +1,21 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using QYZH.InteractiveMagazine.Infrastructure.OSS;
|
||||||
|
using SqlSugar;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading.Channels;
|
||||||
|
using Yitter.IdGenerator;
|
||||||
|
|
||||||
namespace QYZH.InteractiveMagazine.WorkService.Consumers;
|
namespace QYZH.InteractiveMagazine.WorkService.Consumers;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 期刊任务接收消费者(示例)
|
/// 期刊任务接收消费者(示例)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class JournalTaskReceiveConsumer : IQueueConsumer
|
public class JournalTaskReceiveConsumer(ILogger<JournalTaskReceiveConsumer> logger, IConfiguration configuration,
|
||||||
|
IServiceScopeFactory scopeFactory,
|
||||||
|
IWebHostEnvironment webHostEnvironment,
|
||||||
|
IHttpClientFactory httpClientFactory,
|
||||||
|
OssService ossService) : IQueueConsumer
|
||||||
{
|
{
|
||||||
private readonly ILogger<JournalTaskReceiveConsumer> _logger;
|
|
||||||
|
|
||||||
public JournalTaskReceiveConsumer(ILogger<JournalTaskReceiveConsumer> logger)
|
|
||||||
{
|
|
||||||
_logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Exchange => "ex.journal";
|
public string Exchange => "ex.journal";
|
||||||
|
|
||||||
@ -20,20 +23,63 @@ public class JournalTaskReceiveConsumer : IQueueConsumer
|
|||||||
|
|
||||||
public string RoutingKey => "rk.journal.task.receive";
|
public string RoutingKey => "rk.journal.task.receive";
|
||||||
|
|
||||||
public async Task HandleAsync(byte[] message, CancellationToken cancellationToken = default)
|
public async Task HandleAsync(byte[] body, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
var body = Encoding.UTF8.GetString(message);
|
var message = Encoding.UTF8.GetString(body);
|
||||||
_logger.LogInformation("收到期刊任务消息: {Message}", body);
|
logger.LogInformation("收到期刊任务消息: {Message}", message);
|
||||||
|
|
||||||
|
using var scope = scopeFactory.CreateScope();
|
||||||
|
var client = scope.ServiceProvider.GetRequiredService<ISqlSugarClient>();
|
||||||
// TODO: 在此编写具体的消息处理逻辑
|
// TODO: 在此编写具体的消息处理逻辑
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var data = System.Text.Json.JsonSerializer.Deserialize<QuestionData>(message);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
client.Ado.CommitTran();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
client.Ado.RollbackTran();
|
||||||
|
logger.LogError(ex.Message + ex.StackTrace);
|
||||||
|
}
|
||||||
await Task.CompletedTask;
|
await Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task OnErrorAsync(byte[] message, Exception exception)
|
public Task OnErrorAsync(byte[] body, Exception exception)
|
||||||
{
|
{
|
||||||
var body = Encoding.UTF8.GetString(message);
|
var message = Encoding.UTF8.GetString(body);
|
||||||
_logger.LogError(exception, "处理期刊任务消息失败: {Message}", body);
|
logger.LogError(exception, "处理期刊任务消息失败: {Message}", message);
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class QuestionData
|
||||||
|
{
|
||||||
|
public long UserId { get; set; }
|
||||||
|
public long JournalId { get; set; }
|
||||||
|
public long PageId { get; set; }
|
||||||
|
public string PageAnswerUrl { get; set; }
|
||||||
|
public Question[] Questions { get; set; }
|
||||||
|
public DateTime CreatedTime { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Question
|
||||||
|
{
|
||||||
|
public long Id { get; set; }
|
||||||
|
public string Url { get; set; }
|
||||||
|
public string[] AnswerUrl { get; set; }
|
||||||
|
public DateTime AnswerStartTime { get; set; }
|
||||||
|
public DateTime AnswerEndTime { get; set; }
|
||||||
|
public int AnswerTime { get; set; }
|
||||||
|
public int BreakCount { get; set; }
|
||||||
|
public List<BreakTime> BreakTimes { get; set; }
|
||||||
|
}
|
||||||
|
public class BreakTime
|
||||||
|
{
|
||||||
|
public DateTime Time { get; set; }
|
||||||
|
public long WaitTime { get; set; }
|
||||||
|
}
|
||||||
@ -1,33 +0,0 @@
|
|||||||
-- ========================================
|
|
||||||
-- 宠物模块数据结构优化迁移脚本
|
|
||||||
-- 执行前请备份相关表数据
|
|
||||||
-- ========================================
|
|
||||||
|
|
||||||
-- 1. 修改 Pet 表:CurrentEvolutionId int → bigint
|
|
||||||
ALTER TABLE Pet MODIFY COLUMN CurrentEvolutionId BIGINT NOT NULL DEFAULT 0;
|
|
||||||
|
|
||||||
-- 2. 修改 PetEvolution 表:PreviousEvolutionId int → bigint, 删除 ImageUrl
|
|
||||||
ALTER TABLE PetEvolution MODIFY COLUMN PreviousEvolutionId BIGINT NULL;
|
|
||||||
ALTER TABLE PetEvolution DROP COLUMN ImageUrl;
|
|
||||||
|
|
||||||
-- 3. 修改 PetSkin 表:删除 ImageUrl 和 ProductId
|
|
||||||
ALTER TABLE PetSkin DROP COLUMN ImageUrl;
|
|
||||||
ALTER TABLE PetSkin DROP COLUMN ProductId;
|
|
||||||
|
|
||||||
-- 4. 新建 PetSkinImage 表(每个皮肤在每个进化阶段下有一组有序图片)
|
|
||||||
CREATE TABLE IF NOT EXISTS PetSkinImage (
|
|
||||||
Id BIGINT NOT NULL PRIMARY KEY COMMENT '主键(雪花ID)',
|
|
||||||
SkinId BIGINT NOT NULL COMMENT '皮肤Id,关联PetSkin.Id(0表示默认皮肤)',
|
|
||||||
EvolutionStageId BIGINT NOT NULL COMMENT '进化阶段Id,关联PetEvolution.Id',
|
|
||||||
ImageUrl VARCHAR(500) NOT NULL COMMENT '图片地址',
|
|
||||||
SortOrder INT NOT NULL DEFAULT 0 COMMENT '图片顺序(动画帧序号)',
|
|
||||||
Type VARCHAR(50) NOT NULL DEFAULT 'Normal' COMMENT '图片类型: Normal, Special',
|
|
||||||
Status INT NOT NULL DEFAULT 0 COMMENT '基础状态',
|
|
||||||
IsDeleted TINYINT(1) NOT NULL DEFAULT 0 COMMENT '软删除',
|
|
||||||
CreatedBy VARCHAR(100) NULL COMMENT '创建人',
|
|
||||||
CreatedAt DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
|
||||||
UpdatedBy VARCHAR(100) NULL COMMENT '更新人',
|
|
||||||
UpdatedAt DATETIME NULL COMMENT '更新时间',
|
|
||||||
INDEX idx_skin_evolution (SkinId, EvolutionStageId),
|
|
||||||
INDEX idx_sort (SkinId, EvolutionStageId, SortOrder)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='宠物皮肤图片表';
|
|
||||||
Reference in New Issue
Block a user