diff --git a/QYZH.InteractiveMagazine.Infrastructure/Middleware/GlobalExceptionMiddleware.cs b/QYZH.InteractiveMagazine.Infrastructure/Middleware/GlobalExceptionMiddleware.cs index 39b8601..4c28f0b 100644 --- a/QYZH.InteractiveMagazine.Infrastructure/Middleware/GlobalExceptionMiddleware.cs +++ b/QYZH.InteractiveMagazine.Infrastructure/Middleware/GlobalExceptionMiddleware.cs @@ -13,6 +13,14 @@ public class GlobalExceptionMiddleware : IMiddleware { private readonly ILogger _logger; + /// + /// JSON序列化选项(camelCase,与Controller保持一致) + /// + private static readonly JsonSerializerOptions JsonOptions = new() + { + PropertyNamingPolicy = JsonNamingPolicy.CamelCase + }; + /// /// 构造函数 /// @@ -35,7 +43,7 @@ public class GlobalExceptionMiddleware : IMiddleware } catch (BusinessException ex) { - _logger.LogWarning(ex, "业务异常:{Message}", ex.Message); + _logger.LogWarning(ex, "业务异常:{Message},状态码:{ResultCode}", ex.Message, ex.ResultCode); await HandleBusinessExceptionAsync(context, ex); } catch (Exception ex) @@ -46,17 +54,17 @@ public class GlobalExceptionMiddleware : IMiddleware } /// - /// 处理业务异常 + /// 处理业务异常(按业务状态码映射HTTP状态码) /// /// HTTP上下文 /// 业务异常 private static async Task HandleBusinessExceptionAsync(HttpContext context, BusinessException ex) { context.Response.ContentType = "application/json"; - context.Response.StatusCode = StatusCodes.Status400BadRequest; + context.Response.StatusCode = GetHttpStatusCode(ex.ResultCode); - var response = BaseResponse.Fail(ResultCode.FAIL,ex.Message); - var json = JsonSerializer.Serialize(response); + var response = BaseResponse.Fail(ex.ResultCode, ex.Message); + var json = JsonSerializer.Serialize(response, JsonOptions); await context.Response.WriteAsync(json); } @@ -71,9 +79,32 @@ public class GlobalExceptionMiddleware : IMiddleware context.Response.ContentType = "application/json"; context.Response.StatusCode = StatusCodes.Status500InternalServerError; - var response = BaseResponse.Fail("系统内部错误,请稍后重试"); - var json = JsonSerializer.Serialize(response); + var response = BaseResponse.Fail(ResultCode.GLOBAL_ERROR, "系统内部错误,请稍后重试"); + var json = JsonSerializer.Serialize(response, JsonOptions); await context.Response.WriteAsync(json); } + + /// + /// 根据业务状态码获取对应的HTTP状态码 + /// + /// 业务状态码 + /// HTTP状态码 + 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 + }; + } } diff --git a/QYZH.InteractiveMagazine.Infrastructure/Middleware/ModelValidActionFilter.cs b/QYZH.InteractiveMagazine.Infrastructure/Middleware/ModelValidActionFilter.cs index b9729ca..2e77b1b 100644 --- a/QYZH.InteractiveMagazine.Infrastructure/Middleware/ModelValidActionFilter.cs +++ b/QYZH.InteractiveMagazine.Infrastructure/Middleware/ModelValidActionFilter.cs @@ -24,7 +24,7 @@ public class ModelValidActionFilterAttribute : ActionFilterAttribute errorDic.Add(key, errorStr); } } - var result = new BaseResponse>() { code = ResultCode.FAIL }; + var result = new BaseResponse>() { code = ResultCode.BAD_REQUEST }; result.message = string.Join("|", errorDic.Select(e => e.Value).Distinct()); result.result = errorDic; diff --git a/QYZH.InteractiveMagazine.Infrastructure/OSS/OssImageHelper.cs b/QYZH.InteractiveMagazine.Infrastructure/OSS/OssImageHelper.cs index aed0d25..26af79b 100644 --- a/QYZH.InteractiveMagazine.Infrastructure/OSS/OssImageHelper.cs +++ b/QYZH.InteractiveMagazine.Infrastructure/OSS/OssImageHelper.cs @@ -1,6 +1,7 @@ using Microsoft.Extensions.Logging; using QYZH.InteractiveMagazine.Common.Extensions; using QYZH.InteractiveMagazine.Models.Common; +using QYZH.InteractiveMagazine.Models.Dto; namespace QYZH.InteractiveMagazine.Infrastructure.OSS; @@ -87,7 +88,7 @@ public class OssImageHelper catch (Exception ex) when (ex is not BusinessException) { _logger.LogError(ex, "OSS 图片搬运异常,Source: {Source}, Target: {Target}", sourcePath, targetPath); - throw new BusinessException("图片搬运失败,请重试", 500); + throw new BusinessException("图片搬运失败,请重试", ResultCode.GLOBAL_ERROR); } } diff --git a/QYZH.InteractiveMagazine.Infrastructure/OSS/OssService.cs b/QYZH.InteractiveMagazine.Infrastructure/OSS/OssService.cs index 8cdfe25..7d19bcc 100644 --- a/QYZH.InteractiveMagazine.Infrastructure/OSS/OssService.cs +++ b/QYZH.InteractiveMagazine.Infrastructure/OSS/OssService.cs @@ -7,6 +7,8 @@ using CSRedis; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using QYZH.InteractiveMagazine.Common.Extensions; +using QYZH.InteractiveMagazine.Models.Common; +using QYZH.InteractiveMagazine.Models.Dto; using System.Text.Json; using System.Web; @@ -193,6 +195,53 @@ namespace QYZH.InteractiveMagazine.Infrastructure.OSS } } + /// + /// 判断对象是否存在 + /// + /// + /// + 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; + } + } + + /// + /// 获取对象内容流 + /// + /// + /// + 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; + } + } + /// /// 删除多个 /// diff --git a/QYZH.InteractiveMagazine.Models/Common/BusinessException.cs b/QYZH.InteractiveMagazine.Models/Common/BusinessException.cs index 93e17e5..a45725f 100644 --- a/QYZH.InteractiveMagazine.Models/Common/BusinessException.cs +++ b/QYZH.InteractiveMagazine.Models/Common/BusinessException.cs @@ -1,3 +1,5 @@ +using QYZH.InteractiveMagazine.Models.Dto; + namespace QYZH.InteractiveMagazine.Models.Common; /// @@ -10,6 +12,11 @@ public class BusinessException : Exception /// public int Code { get; set; } + /// + /// 业务状态码 + /// + public ResultCode ResultCode { get; set; } = ResultCode.FAIL; + /// /// 无参构造函数 /// @@ -33,6 +40,18 @@ public class BusinessException : Exception public BusinessException(string message, int code) : base(message) { Code = code; + ResultCode = System.Enum.IsDefined(typeof(ResultCode), code) ? (ResultCode)code : ResultCode.FAIL; + } + + /// + /// 构造函数(按业务状态码) + /// + /// 异常消息 + /// 业务状态码 + public BusinessException(string message, ResultCode resultCode) : base(message) + { + ResultCode = resultCode; + Code = (int)resultCode; } /// @@ -62,4 +81,15 @@ public class BusinessException : Exception throw new BusinessException(message); } } + + /// + /// 条件抛出业务异常(带业务状态码) + /// + /// 是否触发 + /// 异常消息 + /// 业务状态码 + public static void ThrowIf(bool isTrue, string message, ResultCode resultCode) + { + if (isTrue) throw new BusinessException(message, resultCode); + } } diff --git a/QYZH.InteractiveMagazine.Models/Dto/BaseResponse.cs b/QYZH.InteractiveMagazine.Models/Dto/BaseResponse.cs index 3e923fa..db1e766 100644 --- a/QYZH.InteractiveMagazine.Models/Dto/BaseResponse.cs +++ b/QYZH.InteractiveMagazine.Models/Dto/BaseResponse.cs @@ -195,5 +195,23 @@ public enum ResultCode FORBIDDEN = 403, [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 } diff --git a/QYZH.InteractiveMagazine.Models/Entity/JournalPageTaskUserAnswerSnapshot.cs b/QYZH.InteractiveMagazine.Models/Entity/JournalPageTaskUserAnswerSnapshot.cs new file mode 100644 index 0000000..300176e --- /dev/null +++ b/QYZH.InteractiveMagazine.Models/Entity/JournalPageTaskUserAnswerSnapshot.cs @@ -0,0 +1,161 @@ +using SqlSugar; + +namespace QYZH.InteractiveMagazine.Models.Entity +{ + /// + /// Snapshot record for a user answer. + /// + [SugarTable("JournalPageTaskUserAnswerSnapshot")] + public class JournalPageTaskUserAnswerSnapshot : SqlSugarBaseEntity + { + /// + /// Source JournalPageTaskUserAnswer record Id. + /// + public long JournalPageTaskUserAnswerId { get; set; } + + /// + /// Journal Id. + /// + public long JournalId { get; set; } + + /// + /// Journal page Id. + /// + public long JournalPageId { get; set; } + + /// + /// Journal page task Id. + /// + public long JournalPageTaskId { get; set; } + + /// + /// Journal page task group Id. + /// + public long JournalPageTaskGroupId { get; set; } + + /// + /// User Id. + /// + public long UserId { get; set; } + + /// + /// Answer result. + /// + public string? Result { get; set; } + + /// + /// Points awarded. + /// + public float Points { get; set; } + + /// + /// Growth points awarded. + /// + public float GrowthPoints { get; set; } + + /// + /// Task score. + /// + public float Score { get; set; } + + /// + /// Question answer image URL. + /// + public string? QuestionAnswerUrl { get; set; } + + /// + /// Answer image URL. + /// + public string? AnswerUrl { get; set; } + + /// + /// Page answer image URL. + /// + public string? PageAnswerUrl { get; set; } + + /// + /// Optimistic concurrency revision. + /// + public int Revision { get; set; } + + /// + /// Answer status. + /// + public int AnswerStatus { get; set; } + + /// + /// Answer start time. + /// + public DateTime AnswerStartTime { get; set; } + + /// + /// Answer end time. + /// + public DateTime AnswerEndTime { get; set; } + + /// + /// Answer duration in seconds. + /// + public int AnswerSeconds { get; set; } + + /// + /// Image recognition result. + /// + public int ImageRecognition { get; set; } + + /// + /// Journal page number. + /// + public int JournalPageNum { get; set; } + + /// + /// Modify count. + /// + public int Modify { get; set; } + + /// + /// Last tag Id. + /// + public long LastTag { get; set; } + + /// + /// Dot page number. + /// + public int DotPageNum { get; set; } + + /// + /// Page result image URL. + /// + public string? PageResultUrl { get; set; } + + /// + /// Question type. + /// + public string? Type { get; set; } + + /// + /// Dot page number text. + /// + public string? DotPageNo { get; set; } + + /// + /// Page answer dot image URL. + /// + public string? PageAnswerDotUrl { get; set; } + + /// + /// Break count. + /// + public int BreakCount { get; set; } + + /// + /// Break time records. + /// + public string? BreakTimes { get; set; } + + /// + /// Assignment status. + /// + public string? AssignmentStatus { get; set; } + } +} diff --git a/QYZH.InteractiveMagazine.Service/AdminAuthService.cs b/QYZH.InteractiveMagazine.Service/AdminAuthService.cs index ae575c0..1aaa911 100644 --- a/QYZH.InteractiveMagazine.Service/AdminAuthService.cs +++ b/QYZH.InteractiveMagazine.Service/AdminAuthService.cs @@ -25,31 +25,31 @@ public class AdminAuthService(BaseRepository adminUserRepository, ICo if (string.IsNullOrWhiteSpace(input.UserName)) { - throw new BusinessException("用户名不能为空", 400); + throw new BusinessException("用户名不能为空", ResultCode.BAD_REQUEST); } 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); if (adminUser == null) { logger.LogWarning("管理员登录失败,用户名不存在: {UserName}", input.UserName); - throw new BusinessException("用户名或密码错误", 401); + throw new BusinessException("用户名或密码错误", ResultCode.DENY); } if (!BCrypt.Net.BCrypt.Verify(input.Password, adminUser.PasswordHash)) { logger.LogWarning("管理员登录失败,密码错误: {UserName}", input.UserName); - throw new BusinessException("用户名或密码错误", 401); + throw new BusinessException("用户名或密码错误", ResultCode.DENY); } if (adminUser.Status != 1) { logger.LogWarning("管理员登录失败,账号已禁用: {UserName}", input.UserName); - throw new BusinessException("账号已被禁用,请联系系统管理员", 403); + throw new BusinessException("账号已被禁用,请联系系统管理员", ResultCode.FORBIDDEN); } var jwtSettings = GetJwtSettings(); @@ -86,7 +86,7 @@ public class AdminAuthService(BaseRepository adminUserRepository, ICo if (adminUser == null) { logger.LogWarning("未找到管理员,ID: {UserId}", userId); - throw new BusinessException("用户不存在", 404); + throw new BusinessException("用户不存在", ResultCode.NOT_FOUND); } return new AdminUserInfoOutput @@ -104,25 +104,25 @@ public class AdminAuthService(BaseRepository adminUserRepository, ICo if (string.IsNullOrWhiteSpace(oldPassword)) { - throw new BusinessException("原密码不能为空", 400); + throw new BusinessException("原密码不能为空", ResultCode.BAD_REQUEST); } if (string.IsNullOrWhiteSpace(newPassword)) { - throw new BusinessException("新密码不能为空", 400); + throw new BusinessException("新密码不能为空", ResultCode.BAD_REQUEST); } var adminUser = await adminUserRepository.GetByIdAsync(userId); if (adminUser == null) { logger.LogWarning("未找到管理员,ID: {UserId}", userId); - throw new BusinessException("用户不存在", 404); + throw new BusinessException("用户不存在", ResultCode.NOT_FOUND); } if (!BCrypt.Net.BCrypt.Verify(oldPassword, adminUser.PasswordHash)) { logger.LogWarning("管理员修改密码失败,原密码错误,ID: {UserId}", userId); - throw new BusinessException("原密码错误", 400); + throw new BusinessException("原密码错误", ResultCode.DENY); } adminUser.PasswordHash = BCrypt.Net.BCrypt.HashPassword(newPassword); @@ -130,7 +130,7 @@ public class AdminAuthService(BaseRepository adminUserRepository, ICo var result = await adminUserRepository.UpdateAsync(adminUser); if (!result) { - throw new BusinessException("修改密码失败", 500); + throw new BusinessException("修改密码失败", ResultCode.GLOBAL_ERROR); } await RedisHelper.DelAsync($"{TokenKeyPrefix}:{userId}"); @@ -151,7 +151,7 @@ public class AdminAuthService(BaseRepository adminUserRepository, ICo if (string.IsNullOrWhiteSpace(jwtSettings.SecretKey)) { - throw new BusinessException("JWT 配置不完整", 500); + throw new BusinessException("JWT 配置不完整", ResultCode.GLOBAL_ERROR); } return jwtSettings; diff --git a/QYZH.InteractiveMagazine.Service/AdminUserService.cs b/QYZH.InteractiveMagazine.Service/AdminUserService.cs index dce70ef..9b61b01 100644 --- a/QYZH.InteractiveMagazine.Service/AdminUserService.cs +++ b/QYZH.InteractiveMagazine.Service/AdminUserService.cs @@ -27,12 +27,12 @@ public class AdminUserService(BaseRepository adminUserRepository, ILo if (string.IsNullOrWhiteSpace(input.UserName)) { - throw new BusinessException("用户名不能为空", 400); + throw new BusinessException("用户名不能为空", ResultCode.BAD_REQUEST); } if (string.IsNullOrWhiteSpace(input.Password)) { - throw new BusinessException("密码不能为空", 400); + throw new BusinessException("密码不能为空", ResultCode.BAD_REQUEST); } // 检查用户名是否已存在 @@ -40,7 +40,7 @@ public class AdminUserService(BaseRepository adminUserRepository, ILo if (existingUser != null) { logger.LogWarning("创建管理员失败,用户名已存在: {UserName}", input.UserName); - throw new BusinessException("用户名已存在", 400); + throw new BusinessException("用户名已存在", ResultCode.CONFLICT); } var adminUser = new AdminUser @@ -60,7 +60,7 @@ public class AdminUserService(BaseRepository adminUserRepository, ILo if (!result) { logger.LogError("管理员创建失败,用户名: {UserName}", input.UserName); - throw new BusinessException("创建管理员失败", 500); + throw new BusinessException("创建管理员失败", ResultCode.GLOBAL_ERROR); } logger.LogInformation("管理员创建成功,用户名: {UserName}, ID: {Id}", input.UserName, adminUser.Id); @@ -79,7 +79,7 @@ public class AdminUserService(BaseRepository adminUserRepository, ILo if (adminUser == null) { logger.LogWarning("未找到要更新的管理员,ID: {Id}", id); - throw new BusinessException("管理员不存在", 404); + throw new BusinessException("管理员不存在", ResultCode.NOT_FOUND); } // 如果用户名有变更,检查是否与其他用户重复 @@ -89,7 +89,7 @@ public class AdminUserService(BaseRepository adminUserRepository, ILo if (existingUser != null && existingUser.Id != id) { logger.LogWarning("更新管理员失败,用户名已存在: {UserName}", input.UserName); - throw new BusinessException("用户名已存在", 400); + throw new BusinessException("用户名已存在", ResultCode.CONFLICT); } adminUser.UserName = input.UserName.Trim(); @@ -111,7 +111,7 @@ public class AdminUserService(BaseRepository adminUserRepository, ILo if (!result) { logger.LogError("管理员更新失败,ID: {Id}", id); - throw new BusinessException("更新管理员失败", 500); + throw new BusinessException("更新管理员失败", ResultCode.GLOBAL_ERROR); } logger.LogInformation("管理员更新成功,ID: {Id}", id); @@ -130,14 +130,14 @@ public class AdminUserService(BaseRepository adminUserRepository, ILo if (adminUser == null) { logger.LogWarning("未找到要删除的管理员,ID: {Id}", id); - throw new BusinessException("管理员不存在", 404); + throw new BusinessException("管理员不存在", ResultCode.NOT_FOUND); } var result = await adminUserRepository.DeleteByIdAsync(id); if (!result) { logger.LogError("管理员删除失败,ID: {Id}", id); - throw new BusinessException("删除管理员失败", 500); + throw new BusinessException("删除管理员失败", ResultCode.GLOBAL_ERROR); } logger.LogInformation("管理员删除成功,ID: {Id}", id); @@ -154,7 +154,7 @@ public class AdminUserService(BaseRepository adminUserRepository, ILo if (adminUser == null) { logger.LogWarning("未找到管理员,ID: {Id}", id); - throw new BusinessException("管理员不存在", 404); + throw new BusinessException("管理员不存在", ResultCode.NOT_FOUND); } return new AdminUserOutput { @@ -178,12 +178,12 @@ public class AdminUserService(BaseRepository adminUserRepository, ILo if (input.PageIndex <= 0) { - throw new BusinessException("页码必须大于0", 400); + throw new BusinessException("页码必须大于0", ResultCode.BAD_REQUEST); } if (input.PageSize <= 0 || input.PageSize > 100) { - throw new BusinessException("每页条数必须在1-100之间", 400); + throw new BusinessException("每页条数必须在1-100之间", ResultCode.BAD_REQUEST); } RefAsync totalNumber = 0; var pageResult = await adminUserRepository.Queryable() @@ -215,7 +215,7 @@ public class AdminUserService(BaseRepository adminUserRepository, ILo if (adminUser == null) { 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; @@ -226,7 +226,7 @@ public class AdminUserService(BaseRepository adminUserRepository, ILo if (!result) { logger.LogError("管理员状态更新失败,ID: {Id}", id); - throw new BusinessException("更新管理员状态失败", 500); + throw new BusinessException("更新管理员状态失败", ResultCode.GLOBAL_ERROR); } logger.LogInformation("管理员状态更新成功,ID: {Id}", id); diff --git a/QYZH.InteractiveMagazine.Service/AiBasePromptService.cs b/QYZH.InteractiveMagazine.Service/AiBasePromptService.cs index d9b4b94..c24ad29 100644 --- a/QYZH.InteractiveMagazine.Service/AiBasePromptService.cs +++ b/QYZH.InteractiveMagazine.Service/AiBasePromptService.cs @@ -25,24 +25,24 @@ public class AiBasePromptService( if (string.IsNullOrWhiteSpace(input.PromptKey)) { - throw new BusinessException("配置标识不能为空", 400); + throw new BusinessException("配置标识不能为空", ResultCode.BAD_REQUEST); } if (string.IsNullOrWhiteSpace(input.PromptName)) { - throw new BusinessException("配置名称不能为空", 400); + throw new BusinessException("配置名称不能为空", ResultCode.BAD_REQUEST); } if (string.IsNullOrWhiteSpace(input.PromptTemplate)) { - throw new BusinessException("Prompt模板内容不能为空", 400); + throw new BusinessException("Prompt模板内容不能为空", ResultCode.BAD_REQUEST); } // 检查PromptKey是否已存在 var exists = await promptRepository.IsAnyAsync(p => p.PromptKey == input.PromptKey.Trim()); if (exists) { - throw new BusinessException($"配置标识 '{input.PromptKey.Trim()}' 已存在", 400); + throw new BusinessException($"配置标识 '{input.PromptKey.Trim()}' 已存在", ResultCode.BAD_REQUEST); } var entity = new AiBasePrompt @@ -64,7 +64,7 @@ public class AiBasePromptService( if (!result) { 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); @@ -97,29 +97,29 @@ public class AiBasePromptService( if (entity == null) { logger.LogWarning("未找到要更新的Prompt配置,ID: {Id}", id); - throw new BusinessException("Prompt配置不存在", 404); + throw new BusinessException("Prompt配置不存在", ResultCode.NOT_FOUND); } if (string.IsNullOrWhiteSpace(input.PromptKey)) { - throw new BusinessException("配置标识不能为空", 400); + throw new BusinessException("配置标识不能为空", ResultCode.BAD_REQUEST); } if (string.IsNullOrWhiteSpace(input.PromptName)) { - throw new BusinessException("配置名称不能为空", 400); + throw new BusinessException("配置名称不能为空", ResultCode.BAD_REQUEST); } if (string.IsNullOrWhiteSpace(input.PromptTemplate)) { - throw new BusinessException("Prompt模板内容不能为空", 400); + throw new BusinessException("Prompt模板内容不能为空", ResultCode.BAD_REQUEST); } // 检查PromptKey是否被其他记录占用 var exists = await promptRepository.IsAnyAsync(p => p.PromptKey == input.PromptKey.Trim() && p.Id != id); if (exists) { - throw new BusinessException($"配置标识 '{input.PromptKey.Trim()}' 已被其他配置使用", 400); + throw new BusinessException($"配置标识 '{input.PromptKey.Trim()}' 已被其他配置使用", ResultCode.BAD_REQUEST); } entity.PromptKey = input.PromptKey.Trim(); @@ -135,7 +135,7 @@ public class AiBasePromptService( if (!result) { logger.LogError("Prompt配置更新失败,ID: {Id}", id); - throw new BusinessException("更新Prompt配置失败", 500); + throw new BusinessException("更新Prompt配置失败", ResultCode.GLOBAL_ERROR); } logger.LogInformation("Prompt配置更新成功,ID: {Id}", id); @@ -168,14 +168,14 @@ public class AiBasePromptService( if (entity == null) { logger.LogWarning("未找到要删除的Prompt配置,ID: {Id}", id); - throw new BusinessException("Prompt配置不存在", 404); + throw new BusinessException("Prompt配置不存在", ResultCode.NOT_FOUND); } var result = await promptRepository.DeleteByIdAsync(id); if (!result) { logger.LogError("Prompt配置删除失败,ID: {Id}", id); - throw new BusinessException("删除Prompt配置失败", 500); + throw new BusinessException("删除Prompt配置失败", ResultCode.GLOBAL_ERROR); } logger.LogInformation("Prompt配置删除成功,ID: {Id}", id); @@ -192,7 +192,7 @@ public class AiBasePromptService( if (entity == null) { logger.LogWarning("未找到Prompt配置,ID: {Id}", id); - throw new BusinessException("Prompt配置不存在", 404); + throw new BusinessException("Prompt配置不存在", ResultCode.NOT_FOUND); } return new AiBasePromptOutput @@ -221,12 +221,12 @@ public class AiBasePromptService( if (input.PageIndex <= 0) { - throw new BusinessException("页码必须大于0", 400); + throw new BusinessException("页码必须大于0", ResultCode.BAD_REQUEST); } if (input.PageSize <= 0 || input.PageSize > 100) { - throw new BusinessException("每页条数必须在1-100之间", 400); + throw new BusinessException("每页条数必须在1-100之间", ResultCode.BAD_REQUEST); } RefAsync totalNumber = 0; @@ -296,7 +296,7 @@ public class AiBasePromptService( if (entity == null) { 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; @@ -307,7 +307,7 @@ public class AiBasePromptService( if (!result) { 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); diff --git a/QYZH.InteractiveMagazine.Service/AiChatService.cs b/QYZH.InteractiveMagazine.Service/AiChatService.cs index 0b33d8c..4b92b69 100644 --- a/QYZH.InteractiveMagazine.Service/AiChatService.cs +++ b/QYZH.InteractiveMagazine.Service/AiChatService.cs @@ -83,7 +83,7 @@ public class AiChatService( { if (string.IsNullOrWhiteSpace(input.Message)) { - throw new BusinessException("消息内容不能为空", 400); + throw new BusinessException("消息内容不能为空", ResultCode.BAD_REQUEST); } var apiKey = configuration["AiChat:ApiKey"]; @@ -95,7 +95,7 @@ public class AiChatService( 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); @@ -132,7 +132,7 @@ public class AiChatService( { var errorContent = await response.Content.ReadAsStringAsync(cancellationToken); logger.LogError("AI聊天服务调用失败,状态码:{StatusCode},响应:{Response}", response.StatusCode, errorContent); - throw new BusinessException($"AI服务调用失败:{response.StatusCode}", 500); + throw new BusinessException($"AI服务调用失败:{response.StatusCode}", ResultCode.GLOBAL_ERROR); } // 流式读取响应体 diff --git a/QYZH.InteractiveMagazine.Service/CheckInConfigService.cs b/QYZH.InteractiveMagazine.Service/CheckInConfigService.cs index f673a1d..e4f68e2 100644 --- a/QYZH.InteractiveMagazine.Service/CheckInConfigService.cs +++ b/QYZH.InteractiveMagazine.Service/CheckInConfigService.cs @@ -27,17 +27,17 @@ public class CheckInConfigService( if (input.DayNumber <= 0) { - throw new BusinessException("连续签到天数必须大于0", 400); + throw new BusinessException("连续签到天数必须大于0", ResultCode.BAD_REQUEST); } if (input.RewardPoints < 0) { - throw new BusinessException("奖励积分不能为负数", 400); + throw new BusinessException("奖励积分不能为负数", ResultCode.BAD_REQUEST); } if (input.BonusPoints < 0) { - throw new BusinessException("额外奖励积分不能为负数", 400); + throw new BusinessException("额外奖励积分不能为负数", ResultCode.BAD_REQUEST); } // 检查同类型下是否已存在相同天数配置 @@ -47,7 +47,7 @@ public class CheckInConfigService( if (exists) { - throw new BusinessException($"该类型下已存在连续{input.DayNumber}天的配置", 400); + throw new BusinessException($"该类型下已存在连续{input.DayNumber}天的配置", ResultCode.BAD_REQUEST); } var config = new CheckInConfig @@ -67,7 +67,7 @@ public class CheckInConfigService( var result = await checkInConfigRepository.InsertAsync(config); if (!result) { - throw new BusinessException("创建签到配置失败", 500); + throw new BusinessException("创建签到配置失败", ResultCode.GLOBAL_ERROR); } logger.LogInformation("签到配置创建成功,ID: {Id}", config.Id); @@ -85,22 +85,22 @@ public class CheckInConfigService( if (config == null) { logger.LogWarning("未找到要更新的签到配置,ID: {Id}", id); - throw new BusinessException("签到配置不存在", 404); + throw new BusinessException("签到配置不存在", ResultCode.NOT_FOUND); } if (input.DayNumber <= 0) { - throw new BusinessException("连续签到天数必须大于0", 400); + throw new BusinessException("连续签到天数必须大于0", ResultCode.BAD_REQUEST); } if (input.RewardPoints < 0) { - throw new BusinessException("奖励积分不能为负数", 400); + throw new BusinessException("奖励积分不能为负数", ResultCode.BAD_REQUEST); } if (input.BonusPoints < 0) { - throw new BusinessException("额外奖励积分不能为负数", 400); + throw new BusinessException("额外奖励积分不能为负数", ResultCode.BAD_REQUEST); } // 检查同类型下是否已存在相同天数配置(排除自身) @@ -110,7 +110,7 @@ public class CheckInConfigService( if (exists) { - throw new BusinessException($"该类型下已存在连续{input.DayNumber}天的配置", 400); + throw new BusinessException($"该类型下已存在连续{input.DayNumber}天的配置", ResultCode.BAD_REQUEST); } config.DayNumber = input.DayNumber; @@ -123,7 +123,7 @@ public class CheckInConfigService( var updateResult = await checkInConfigRepository.UpdateAsync(config); if (!updateResult) { - throw new BusinessException("更新签到配置失败", 500); + throw new BusinessException("更新签到配置失败", ResultCode.GLOBAL_ERROR); } logger.LogInformation("签到配置更新成功,ID: {Id}", id); @@ -141,7 +141,7 @@ public class CheckInConfigService( if (config == null) { logger.LogWarning("未找到要删除的签到配置,ID: {Id}", id); - throw new BusinessException("签到配置不存在", 404); + throw new BusinessException("签到配置不存在", ResultCode.NOT_FOUND); } var result = await checkInConfigRepository.Context.Updateable() @@ -156,7 +156,7 @@ public class CheckInConfigService( if (result <= 0) { - throw new BusinessException("删除签到配置失败", 500); + throw new BusinessException("删除签到配置失败", ResultCode.GLOBAL_ERROR); } logger.LogInformation("签到配置删除成功,ID: {Id}", id); @@ -170,7 +170,7 @@ public class CheckInConfigService( var config = await checkInConfigRepository.GetByIdAsync(id); if (config == null) { - throw new BusinessException("签到配置不存在", 404); + throw new BusinessException("签到配置不存在", ResultCode.NOT_FOUND); } return MapToOutput(config); @@ -185,12 +185,12 @@ public class CheckInConfigService( if (input.PageIndex <= 0) { - throw new BusinessException("页码必须大于0", 400); + throw new BusinessException("页码必须大于0", ResultCode.BAD_REQUEST); } if (input.PageSize <= 0 || input.PageSize > 100) { - throw new BusinessException("每页条数必须在1-100之间", 400); + throw new BusinessException("每页条数必须在1-100之间", ResultCode.BAD_REQUEST); } RefAsync totalNumber = 0; @@ -217,7 +217,7 @@ public class CheckInConfigService( if (config == null) { logger.LogWarning("未找到要更新状态的签到配置,ID: {Id}", id); - throw new BusinessException("签到配置不存在", 404); + throw new BusinessException("签到配置不存在", ResultCode.NOT_FOUND); } config.Status = config.Status == (int)DefaultStatusEnum.Active @@ -230,7 +230,7 @@ public class CheckInConfigService( if (!result) { logger.LogError("签到配置状态更新失败,ID: {Id}", id); - throw new BusinessException("更新签到配置状态失败", 500); + throw new BusinessException("更新签到配置状态失败", ResultCode.GLOBAL_ERROR); } logger.LogInformation("签到配置状态更新成功,ID: {Id}, Status: {Status}", id, config.Status); diff --git a/QYZH.InteractiveMagazine.Service/CheckInService.cs b/QYZH.InteractiveMagazine.Service/CheckInService.cs index ffdde75..f967216 100644 --- a/QYZH.InteractiveMagazine.Service/CheckInService.cs +++ b/QYZH.InteractiveMagazine.Service/CheckInService.cs @@ -2,6 +2,7 @@ using Microsoft.Extensions.Logging; using QYZH.InteractiveMagazine.Common.Extensions; using QYZH.InteractiveMagazine.IService; using QYZH.InteractiveMagazine.Models.Common; +using QYZH.InteractiveMagazine.Models.Dto; using QYZH.InteractiveMagazine.Models.Dto.CheckIn; using QYZH.InteractiveMagazine.Models.Dto.Compensation; using QYZH.InteractiveMagazine.Models.Dto.Pet; @@ -44,7 +45,7 @@ public class CheckInService( if (alreadyCheckedIn) { - throw new BusinessException("今日已签到,请明天再来", 400); + throw new BusinessException("今日已签到,请明天再来", ResultCode.BAD_REQUEST); } // 2. 计算连续签到天数 @@ -60,7 +61,7 @@ public class CheckInService( if (user == null) { - throw new BusinessException("用户不存在", 404); + throw new BusinessException("用户不存在", ResultCode.NOT_FOUND); } // 5. 查询用户宠物(如果有) @@ -226,7 +227,7 @@ public class CheckInService( targetDate = targetDate.Date; if (targetDate >= DateTime.Now.Date) - throw new BusinessException("只能补签过去的日期", 400); + throw new BusinessException("只能补签过去的日期", ResultCode.BAD_REQUEST); // 检查目标日期是否已有签到记录 var alreadyCheckedIn = await checkInRecordRepository.Context.Queryable() @@ -235,7 +236,7 @@ public class CheckInService( .AnyAsync(); 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() @@ -248,7 +249,7 @@ public class CheckInService( .FirstAsync(); if (makeUpCard == null) - throw new BusinessException("补签卡不足,无法补签", 400); + throw new BusinessException("补签卡不足,无法补签", ResultCode.BAD_REQUEST); // 查询用户信息 var user = await checkInRecordRepository.Context.Queryable() @@ -256,7 +257,7 @@ public class CheckInService( .FirstAsync(); if (user == null) - throw new BusinessException("用户不存在", 404); + throw new BusinessException("用户不存在", ResultCode.NOT_FOUND); // 查询宠物 var pet = await checkInRecordRepository.Context.Queryable() diff --git a/QYZH.InteractiveMagazine.Service/CommunityMessageService.cs b/QYZH.InteractiveMagazine.Service/CommunityMessageService.cs index 6b711a8..b0e95ac 100644 --- a/QYZH.InteractiveMagazine.Service/CommunityMessageService.cs +++ b/QYZH.InteractiveMagazine.Service/CommunityMessageService.cs @@ -24,8 +24,8 @@ public class CommunityMessageService(BaseRepository messageRep { logger.LogInformation("正在查询社区消息列表,页码: {PageIndex}, 每页条数: {PageSize}", input.PageIndex, input.PageSize); - if (input.PageIndex <= 0) throw new BusinessException("页码必须大于0", 400); - if (input.PageSize <= 0 || input.PageSize > 100) throw new BusinessException("每页条数必须在1-100之间", 400); + if (input.PageIndex <= 0) throw new BusinessException("页码必须大于0", ResultCode.BAD_REQUEST); + if (input.PageSize <= 0 || input.PageSize > 100) throw new BusinessException("每页条数必须在1-100之间", ResultCode.BAD_REQUEST); RefAsync totalNumber = 0; var pageResult = await messageRepository.Queryable() @@ -75,7 +75,7 @@ public class CommunityMessageService(BaseRepository messageRep if (message == null) { logger.LogWarning("未找到社区消息,ID: {Id}", id); - throw new BusinessException("消息不存在", 404); + throw new BusinessException("消息不存在", ResultCode.NOT_FOUND); } return new AdminMessageDetailOutput @@ -112,14 +112,14 @@ public class CommunityMessageService(BaseRepository messageRep if (message == null) { logger.LogWarning("未找到要删除的社区消息,ID: {Id}", id); - throw new BusinessException("消息不存在", 404); + throw new BusinessException("消息不存在", ResultCode.NOT_FOUND); } var result = await messageRepository.DeleteByIdAsync(id); if (!result) { logger.LogError("社区消息删除失败,ID: {Id}", id); - throw new BusinessException("删除消息失败", 500); + throw new BusinessException("删除消息失败", ResultCode.GLOBAL_ERROR); } logger.LogInformation("社区消息删除成功,ID: {Id}", id); @@ -134,14 +134,14 @@ public class CommunityMessageService(BaseRepository messageRep 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); if (message == null) { logger.LogWarning("未找到社区消息,ID: {Id}", id); - throw new BusinessException("消息不存在", 404); + throw new BusinessException("消息不存在", ResultCode.NOT_FOUND); } message.Status = status; @@ -152,7 +152,7 @@ public class CommunityMessageService(BaseRepository messageRep if (!result) { logger.LogError("社区消息冻结状态更新失败,ID: {Id}", id); - throw new BusinessException("更新冻结状态失败", 500); + throw new BusinessException("更新冻结状态失败", ResultCode.GLOBAL_ERROR); } logger.LogInformation("社区消息冻结状态更新成功,ID: {Id}, Status: {Status}", id, status); @@ -167,14 +167,14 @@ public class CommunityMessageService(BaseRepository messageRep 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); if (message == null) { logger.LogWarning("未找到社区消息,ID: {Id}", id); - throw new BusinessException("消息不存在", 404); + throw new BusinessException("消息不存在", ResultCode.NOT_FOUND); } message.IsFeatured = isFeatured; @@ -185,7 +185,7 @@ public class CommunityMessageService(BaseRepository messageRep if (!result) { logger.LogError("社区消息精选设置失败,ID: {Id}", id); - throw new BusinessException("设置精选失败", 500); + throw new BusinessException("设置精选失败", ResultCode.GLOBAL_ERROR); } logger.LogInformation("社区消息精选设置成功,ID: {Id}, IsFeatured: {IsFeatured}", id, isFeatured); @@ -202,7 +202,7 @@ public class CommunityMessageService(BaseRepository messageRep if (message == null) { logger.LogWarning("未找到社区消息,ID: {Id}", id); - throw new BusinessException("消息不存在", 404); + throw new BusinessException("消息不存在", ResultCode.NOT_FOUND); } message.SortOrder = sortOrder; @@ -213,7 +213,7 @@ public class CommunityMessageService(BaseRepository messageRep if (!result) { logger.LogError("社区消息排序权重设置失败,ID: {Id}", id); - throw new BusinessException("设置排序权重失败", 500); + throw new BusinessException("设置排序权重失败", ResultCode.GLOBAL_ERROR); } logger.LogInformation("社区消息排序权重设置成功,ID: {Id}, SortOrder: {SortOrder}", id, sortOrder); @@ -228,7 +228,7 @@ public class CommunityMessageService(BaseRepository messageRep if (ids == null || ids.Count == 0) { - throw new BusinessException("消息ID列表不能为空", 400); + throw new BusinessException("消息ID列表不能为空", ResultCode.BAD_REQUEST); } var result = await Context.Updateable() diff --git a/QYZH.InteractiveMagazine.Service/CompensationManageService.cs b/QYZH.InteractiveMagazine.Service/CompensationManageService.cs index b0ae7bf..71fbfff 100644 --- a/QYZH.InteractiveMagazine.Service/CompensationManageService.cs +++ b/QYZH.InteractiveMagazine.Service/CompensationManageService.cs @@ -73,10 +73,10 @@ public class CompensationManageService( var task = await compensationTaskRepository.GetByIdAsync(taskId); if (task == null) - throw new BusinessException("补偿任务不存在", 404); + throw new BusinessException("补偿任务不存在", ResultCode.NOT_FOUND); 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,清零重试次数,设置立即执行 await compensationTaskRepository.Context.Updateable() @@ -116,10 +116,10 @@ public class CompensationManageService( var task = await compensationTaskRepository.GetByIdAsync(taskId); if (task == null) - throw new BusinessException("补偿任务不存在", 404); + throw new BusinessException("补偿任务不存在", ResultCode.NOT_FOUND); if (task.Status == (int)CompensationTaskStatusEnum.Success) - throw new BusinessException("该任务已经是成功状态,无需标记", 400); + throw new BusinessException("该任务已经是成功状态,无需标记", ResultCode.BAD_REQUEST); // 标记为 Success await compensationTaskRepository.Context.Updateable() @@ -184,7 +184,7 @@ public class CompensationManageService( .FirstAsync(); if (result == null) - throw new BusinessException("补偿任务不存在", 404); + throw new BusinessException("补偿任务不存在", ResultCode.NOT_FOUND); return result; } diff --git a/QYZH.InteractiveMagazine.Service/JournalCatalogService.cs b/QYZH.InteractiveMagazine.Service/JournalCatalogService.cs index 5d43121..4401c29 100644 --- a/QYZH.InteractiveMagazine.Service/JournalCatalogService.cs +++ b/QYZH.InteractiveMagazine.Service/JournalCatalogService.cs @@ -5,6 +5,7 @@ using QYZH.InteractiveMagazine.Infrastructure.OSS; using QYZH.InteractiveMagazine.IService; using QYZH.InteractiveMagazine.Models.Base; using QYZH.InteractiveMagazine.Models.Common; +using QYZH.InteractiveMagazine.Models.Dto; using QYZH.InteractiveMagazine.Models.Dto.Journal; using QYZH.InteractiveMagazine.Models.Entity; using QYZH.InteractiveMagazine.Models.Enum; @@ -35,10 +36,10 @@ public class JournalCatalogService : BaseRepository, IJournalCat public async Task ImportAsync(JournalImportDto input) { var Journals = await Queryable().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); - BusinessException.ThrowIf(pageNum != 0, "已经存在书页"); + BusinessException.ThrowIf(pageNum != 0, "已经存在书页", ResultCode.CONFLICT); var JournalCatalog = new JournalCatalog() @@ -106,7 +107,7 @@ public class JournalCatalogService : BaseRepository, IJournalCat public async Task> GetJournalCatalogListAsync(long JournalId) { var Journal = await Queryable().Where(w => w.Id == JournalId).FirstAsync(); - BusinessException.ThrowIf(Journal.IsNull(), "未找到书本"); + BusinessException.ThrowIf(Journal.IsNull(), "未找到书本", ResultCode.NOT_FOUND); var pageNumList = await _JournalPageRepository.Queryable() .InnerJoin((a, b) => a.JournalCatalogId == b.Id) @@ -136,7 +137,7 @@ public class JournalCatalogService : BaseRepository, IJournalCat public async Task> GetJournalCataloTreeAsync(long JournalId) { var Journal = await Queryable().Where(w => w.Id == JournalId).FirstAsync(); - BusinessException.ThrowIf(Journal.IsNull(), "未找到书本"); + BusinessException.ThrowIf(Journal.IsNull(), "未找到书本", ResultCode.NOT_FOUND); // 先查询所有目录 var allCatalogs = await base.Queryable() @@ -276,13 +277,13 @@ public class JournalCatalogService : BaseRepository, IJournalCat public async Task ImportCatalogAsync(long JournalId, List dtos) { 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().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 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 { @@ -352,7 +353,7 @@ public class JournalCatalogService : BaseRepository, IJournalCat if (input.Type == 1) { var Journal = await Queryable().Where(w => w.Id == input.JournalId).FirstAsync(); - BusinessException.ThrowIf(Journal.IsNull(), "未找到书本"); + BusinessException.ThrowIf(Journal.IsNull(), "未找到书本", ResultCode.NOT_FOUND); //var dotMatrixPage = new DotMatrixPage() //{ @@ -390,10 +391,10 @@ public class JournalCatalogService : BaseRepository, IJournalCat { // 删除目录 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)); - BusinessException.ThrowIf(pages.IsNull(), $"删除数据失败"); + BusinessException.ThrowIf(pages.IsNull(), $"删除数据失败", ResultCode.GLOBAL_ERROR); //var x = await _JournalPageRepository.DeleteAsync(w => ids.Contains(w.JournalCatalogId)); @@ -406,14 +407,14 @@ public class JournalCatalogService : BaseRepository, IJournalCat { // 1. 获取源节点并校验 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. 校验目标父节点(如果指定) if (input.TargetParentId > 0) { 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 () => diff --git a/QYZH.InteractiveMagazine.Service/JournalPageService.cs b/QYZH.InteractiveMagazine.Service/JournalPageService.cs index 9bd7c93..cbcaf57 100644 --- a/QYZH.InteractiveMagazine.Service/JournalPageService.cs +++ b/QYZH.InteractiveMagazine.Service/JournalPageService.cs @@ -9,6 +9,7 @@ using QYZH.InteractiveMagazine.Infrastructure.OSS; using QYZH.InteractiveMagazine.Infrastructure.RabbitMQ; using QYZH.InteractiveMagazine.IService; using QYZH.InteractiveMagazine.Models.Common; +using QYZH.InteractiveMagazine.Models.Dto; using QYZH.InteractiveMagazine.Models.Dto.Journal; using QYZH.InteractiveMagazine.Models.Entity; using QYZH.InteractiveMagazine.Models.Enum; @@ -34,9 +35,9 @@ public class JournalPageService(BaseRepository JournalRepository, { 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(); //var dotMatrixpages = new List(); @@ -65,7 +66,7 @@ public class JournalPageService(BaseRepository JournalRepository, { //using var uow = Context.Ado.BeginTran(); var pageData = await base.InsertRangeAsync(pages); - BusinessException.ThrowIf(pageData.IsNull(), "创建页失败"); + BusinessException.ThrowIf(pageData.IsNull(), "创建页失败", ResultCode.GLOBAL_ERROR); //var result = await dotMatrixPageRepository.InsertRangeAsync(dotMatrixpages); //BusinessException.ThrowIf(result, "创建点阵页失败"); @@ -77,12 +78,12 @@ public class JournalPageService(BaseRepository JournalRepository, public async Task UpdateAsync(PageLayoutInput input) { 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); - 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 () => { //await dotMatrixPageRepository.Updateable().SetColumns(s => s.Area == input.Layout) @@ -115,21 +116,24 @@ public class JournalPageService(BaseRepository JournalRepository, public async Task UpdatePageNoAsync(long 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(); - BusinessException.ThrowIf(journalPageList.Count == 0, "此期刊不存在任何书页"); + BusinessException.ThrowIf(journalPageList.Count == 0, "此期刊不存在任何书页", ResultCode.NOT_FOUND); - var uploadPdfUrl = DomainHelper.OssFullUrl(journalEntity?.PdfUrl!); - BusinessException.ThrowIf(string.IsNullOrWhiteSpace(uploadPdfUrl), "此期刊上传的PDF路径错误,请检查期刊PDF文件是否上传成功"); + var uploadPdfKey = journalEntity?.PdfUrl?.RemoveDomain(); + 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); //验证是否上传了PDF文件 - var response = await httpClientFactory.CreateClient().SendAsync(new HttpRequestMessage(HttpMethod.Head, uploadPdfUrl)); - BusinessException.ThrowIf(response.StatusCode != HttpStatusCode.OK, "获取期刊上传的PDF文件失败,请检查PDF文件是否上传成功"); + var isPdfExists = ossService.DoesObjectExist(uploadPdfKey); + BusinessException.ThrowIf(!isPdfExists, "获取期刊上传的PDF文件失败,请检查PDF文件是否上传成功", ResultCode.GLOBAL_ERROR); journalEntity.Status = (int)JournalStatusEnum.Codeing; @@ -154,14 +158,14 @@ public class JournalPageService(BaseRepository JournalRepository, return await UseTranAsync(async () => { 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(); - BusinessException.ThrowIf(bookPageList.Count == 0, "此书不存在任何书页"); + BusinessException.ThrowIf(bookPageList.Count == 0, "此书不存在任何书页", ResultCode.NOT_FOUND); journalEntity.Status = (int)request.Status!.Value; journalEntity.UpdatedAt = DateTime.Now; @@ -177,7 +181,7 @@ public class JournalPageService(BaseRepository JournalRepository, { 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++) diff --git a/QYZH.InteractiveMagazine.Service/JournalPageTaskService.cs b/QYZH.InteractiveMagazine.Service/JournalPageTaskService.cs index 504f9e5..efb5ae4 100644 --- a/QYZH.InteractiveMagazine.Service/JournalPageTaskService.cs +++ b/QYZH.InteractiveMagazine.Service/JournalPageTaskService.cs @@ -3,6 +3,7 @@ using QYZH.InteractiveMagazine.Common.Extensions; using QYZH.InteractiveMagazine.Infrastructure.OSS; using QYZH.InteractiveMagazine.IService; using QYZH.InteractiveMagazine.Models.Common; +using QYZH.InteractiveMagazine.Models.Dto; using QYZH.InteractiveMagazine.Models.Dto.Journal; using QYZH.InteractiveMagazine.Models.Entity; using QYZH.InteractiveMagazine.Models.Enum; @@ -18,7 +19,7 @@ public class JournalPageTaskService(BaseRepository journalRepository, O public async Task InsertAsync(JournalPageTaskAddInput input) { 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(); map.Id = YitIdHelper.NextId(); @@ -28,7 +29,7 @@ public class JournalPageTaskService(BaseRepository journalRepository, O { var startNo = $"{no[0]}-{no[1]}-{no[2]}-1"; 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.Type = groupTask.Type; } @@ -42,13 +43,13 @@ public class JournalPageTaskService(BaseRepository journalRepository, O public async Task UpdateAsync(JournalPageTaskUpdateInput input) { 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(); - 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(); - BusinessException.ThrowIf(sameTask.IsNotEmpty(), "已经存在相同题号题目"); + BusinessException.ThrowIf(sameTask.IsNotEmpty(), "已经存在相同题号题目", ResultCode.CONFLICT); var key = $"journal/{task.JournalId}/{task.JournalPageId}/{task.GroupId}"; @@ -74,7 +75,7 @@ public class JournalPageTaskService(BaseRepository journalRepository, O { var startNo = $"{no[0]}-{no[1]}-{no[2]}-1"; 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.Type = groupTask.Type; } @@ -124,7 +125,7 @@ public class JournalPageTaskService(BaseRepository journalRepository, O public async Task DeleteAsync(long id) { 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}"; @@ -139,7 +140,7 @@ public class JournalPageTaskService(BaseRepository journalRepository, O public async Task ComplementAsync(JournalPageTaskComplementInput input) { 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()) { @@ -159,7 +160,7 @@ public class JournalPageTaskService(BaseRepository journalRepository, O public async Task AddAnswerAsync(JournalTaskAnswerAddInput input) { 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}"; input.Answer = Deal(null, input.Answer, key, "answer"); @@ -181,7 +182,7 @@ public class JournalPageTaskService(BaseRepository journalRepository, O public async Task UpdateAnswerAsync(JournalTaskAnswerUpdateInput input) { 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 key = $"journal/{task.JournalId}/{task.JournalPageId}/{task.GroupId}"; @@ -199,7 +200,7 @@ public class JournalPageTaskService(BaseRepository journalRepository, O public async Task DeleteAnswerAsync(long id) { 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 key = $"journal/{task.JournalId}/{task.JournalPageId}/{task.GroupId}"; diff --git a/QYZH.InteractiveMagazine.Service/JournalService.cs b/QYZH.InteractiveMagazine.Service/JournalService.cs index 129a5dc..ce5e227 100644 --- a/QYZH.InteractiveMagazine.Service/JournalService.cs +++ b/QYZH.InteractiveMagazine.Service/JournalService.cs @@ -68,7 +68,7 @@ public class JournalService(BaseRepository JournalPageRepository, /// 新杂志ID public async Task> AddAsync(JournalAddDto input) { - BusinessException.ThrowIf(string.IsNullOrWhiteSpace(input.Name), "书籍名称不能为空"); + BusinessException.ThrowIf(string.IsNullOrWhiteSpace(input.Name), "书籍名称不能为空", ResultCode.BAD_REQUEST); var journal = new Journal { @@ -114,7 +114,7 @@ public class JournalService(BaseRepository JournalPageRepository, var res = await base.InsertAsync(journal); if (!res) { - new BusinessException("创建失败"); + new BusinessException("创建失败", ResultCode.GLOBAL_ERROR); } logger.LogInformation("杂志创建成功,ID: {Id}, 名称: {Name}", journal.Id, input.Name); return BaseResponse.Success(journal.Id); @@ -129,8 +129,8 @@ public class JournalService(BaseRepository JournalPageRepository, { var Journal = await base.GetByIdAsync(input.Id); - BusinessException.ThrowIf(Journal.IsNull(), "不存在的Id"); - BusinessException.ThrowIf(Journal.Status == (int)JournalStatusEnum.Archive, "已归档不可编辑"); + BusinessException.ThrowIf(Journal.IsNull(), "不存在的Id", ResultCode.NOT_FOUND); + BusinessException.ThrowIf(Journal.Status == (int)JournalStatusEnum.Archive, "已归档不可编辑", ResultCode.CONFLICT); if (string.IsNullOrWhiteSpace(input.Cover)) { Journal.Cover = null; @@ -204,8 +204,8 @@ public class JournalService(BaseRepository JournalPageRepository, public async Task DeleteAsync(List ids) { - BusinessException.ThrowIf(!base.Queryable().Any(w => ids.Contains(w.Id)), "ID不存在"); - 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)), "ID不存在", ResultCode.NOT_FOUND); + BusinessException.ThrowIf(base.Queryable().Any(w => ids.Contains(w.Id) && w.Status == (int)JournalStatusEnum.Archive), "已归档不可删除", ResultCode.CONFLICT); var result = await UseTranAsync(async () => { await base.DeleteAsync(d => ids.Contains(d.Id)); @@ -282,11 +282,11 @@ public class JournalService(BaseRepository JournalPageRepository, public async Task PrintCodeAsync(long id) { var Journal = await base.Queryable().Where(w => w.Id == id).FirstAsync(); - BusinessException.ThrowIf(Journal.IsNull(), "不存在书"); - BusinessException.ThrowIf(Journal.Status == (int)JournalStatusEnum.Codeing, "正在生成中..."); + BusinessException.ThrowIf(Journal.IsNull(), "不存在书", ResultCode.NOT_FOUND); + BusinessException.ThrowIf(Journal.Status == (int)JournalStatusEnum.Codeing, "正在生成中...", ResultCode.CONFLICT); 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() { @@ -315,8 +315,8 @@ public class JournalService(BaseRepository JournalPageRepository, { var book = await base.GetByIdAsync(id); var tasks = await Context.Queryable().Where(w => w.JournalId == id).ToListAsync(); - BusinessException.ThrowIf(tasks.Count == 0 && status == JournalStatusEnum.Archive, "未添加任何题目,无法归档"); - 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.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())}未保存,无法归档", ResultCode.UNPROCESSABLE_ENTITY); var res = await base.Updateable().SetColumns(s => s.Status, status).Where(w => w.Id == id).ExecuteCommandAsync() > 0; return res; } diff --git a/QYZH.InteractiveMagazine.Service/MedalService.cs b/QYZH.InteractiveMagazine.Service/MedalService.cs index f18ec25..c60bade 100644 --- a/QYZH.InteractiveMagazine.Service/MedalService.cs +++ b/QYZH.InteractiveMagazine.Service/MedalService.cs @@ -27,12 +27,12 @@ public class MedalService(BaseRepository medalRepository, IOptions medalRepository, IOptions 0) @@ -74,7 +74,7 @@ public class MedalService(BaseRepository medalRepository, IOptions medalRepository, IOptions medalRepository, IOptions medalRepository, IOptions medalRepository, IOptions medalRepository, IOptions medalRepository, IOptions medalRepository, IOptions medalRepository, IOptions 100) { - throw new BusinessException("每页条数必须在1-100之间", 400); + throw new BusinessException("每页条数必须在1-100之间", ResultCode.BAD_REQUEST); } RefAsync totalNumber = 0; @@ -266,7 +266,7 @@ public class MedalService(BaseRepository medalRepository, IOptions medalRepository, IOptions medalRepository, IOptions medalRepository, IOptions() @@ -393,7 +393,7 @@ public class MedalService(BaseRepository medalRepository, IOptions medalRepository, IOptions medalRepository, IOptions {After}, 进化: {HasEvolved}", @@ -402,10 +402,10 @@ public class PetService( public async Task CreateTemplateAsync(PetTemplateInput input) { if (string.IsNullOrWhiteSpace(input.Name)) - throw new BusinessException("模板名称不能为空", 400); + throw new BusinessException("模板名称不能为空", ResultCode.BAD_REQUEST); if (input.Evolutions == null || input.Evolutions.Count == 0) - throw new BusinessException("至少需要一个进化阶段", 400); + throw new BusinessException("至少需要一个进化阶段", ResultCode.BAD_REQUEST); PetTemplate template = null!; @@ -430,7 +430,7 @@ public class PetService( var inserted = await petTemplateRepository.InsertAsync(template); if (!inserted) - throw new BusinessException("创建宠物模板失败", 500); + throw new BusinessException("创建宠物模板失败", ResultCode.GLOBAL_ERROR); // 2. 按 StageLevel 排序,依次创建进化阶段 var sortedEvolutions = input.Evolutions.OrderBy(e => e.StageLevel).ToList(); @@ -458,7 +458,7 @@ public class PetService( var evoInserted = await petEvolutionRepository.InsertAsync(evolution); if (!evoInserted) - throw new BusinessException($"创建进化阶段 [{evoInput.StageName}] 失败", 500); + throw new BusinessException($"创建进化阶段 [{evoInput.StageName}] 失败", ResultCode.GLOBAL_ERROR); // 记录初始阶段(第一个) if (previousEvolution == null) @@ -560,10 +560,10 @@ public class PetService( { var template = await petTemplateRepository.GetByIdAsync(id); if (template == null || template.IsDeleted) - throw new BusinessException("宠物模板不存在", 404); + throw new BusinessException("宠物模板不存在", ResultCode.NOT_FOUND); if (string.IsNullOrWhiteSpace(input.Name)) - throw new BusinessException("模板名称不能为空", 400); + throw new BusinessException("模板名称不能为空", ResultCode.BAD_REQUEST); template.Name = input.Name.Trim(); template.Description = input.Description; @@ -575,7 +575,7 @@ public class PetService( var result = await petTemplateRepository.UpdateAsync(template); if (!result) - throw new BusinessException("更新宠物模板失败", 500); + throw new BusinessException("更新宠物模板失败", ResultCode.GLOBAL_ERROR); logger.LogInformation("更新宠物模板成功,Id: {Id}", id); return BuildTemplateOutput(template); @@ -588,18 +588,18 @@ public class PetService( { var template = await petTemplateRepository.GetByIdAsync(id); if (template == null || template.IsDeleted) - throw new BusinessException("宠物模板不存在", 404); + throw new BusinessException("宠物模板不存在", ResultCode.NOT_FOUND); if (template.Type == PetTemplateTypeEnum.Default) - throw new BusinessException("默认模板不允许删除", 400); + throw new BusinessException("默认模板不允许删除", ResultCode.BAD_REQUEST); // 校验是否有用户宠物实例关联 var hasUserPet = petRepository.Context.Queryable() .Any(p => p.TemplateId == id && !p.IsDeleted); if (hasUserPet) - throw new BusinessException("该模板下存在用户宠物实例,无法删除", 400); + throw new BusinessException("该模板下存在用户宠物实例,无法删除", ResultCode.BAD_REQUEST); template.IsDeleted = true; template.UpdatedBy = "System"; @@ -616,7 +616,7 @@ public class PetService( { var template = await petTemplateRepository.GetByIdAsync(id); if (template == null || template.IsDeleted) - throw new BusinessException("宠物模板不存在", 404); + throw new BusinessException("宠物模板不存在", ResultCode.NOT_FOUND); return BuildTemplateOutput(template); } @@ -663,7 +663,7 @@ public class PetService( { var template = await petTemplateRepository.GetByIdAsync(id); if (template == null || template.IsDeleted) - throw new BusinessException("宠物模板不存在", 404); + throw new BusinessException("宠物模板不存在", ResultCode.NOT_FOUND); template.Status = template.Status == (int)DefaultStatusEnum.Active ? (int)DefaultStatusEnum.Inactive @@ -703,16 +703,16 @@ public class PetService( public async Task CreateEvolutionAsync(PetEvolutionInput input) { if (input.TemplateId <= 0) - throw new BusinessException("模板Id不能为空", 400); + throw new BusinessException("模板Id不能为空", ResultCode.BAD_REQUEST); if (string.IsNullOrWhiteSpace(input.StageName)) - throw new BusinessException("阶段名称不能为空", 400); + throw new BusinessException("阶段名称不能为空", ResultCode.BAD_REQUEST); // 校验模板是否存在 var templateExists = petTemplateRepository.Context.Queryable() .Any(t => t.Id == input.TemplateId && !t.IsDeleted); if (!templateExists) - throw new BusinessException("宠物模板不存在", 404); + throw new BusinessException("宠物模板不存在", ResultCode.NOT_FOUND); var evolution = new PetEvolution { @@ -732,7 +732,7 @@ public class PetService( var result = await petEvolutionRepository.InsertAsync(evolution); if (!result) - throw new BusinessException("创建进化阶段失败", 500); + throw new BusinessException("创建进化阶段失败", ResultCode.GLOBAL_ERROR); logger.LogInformation("创建进化阶段成功,Id: {Id}, StageName: {StageName}", evolution.Id, evolution.StageName); return BuildEvolutionOutput(evolution); @@ -745,10 +745,10 @@ public class PetService( { var evolution = await petEvolutionRepository.GetByIdAsync(id); if (evolution == null || evolution.IsDeleted) - throw new BusinessException("进化阶段不存在", 404); + throw new BusinessException("进化阶段不存在", ResultCode.NOT_FOUND); if (string.IsNullOrWhiteSpace(input.StageName)) - throw new BusinessException("阶段名称不能为空", 400); + throw new BusinessException("阶段名称不能为空", ResultCode.BAD_REQUEST); evolution.TemplateId = input.TemplateId; evolution.StageName = input.StageName.Trim(); @@ -761,7 +761,7 @@ public class PetService( var result = await petEvolutionRepository.UpdateAsync(evolution); if (!result) - throw new BusinessException("更新进化阶段失败", 500); + throw new BusinessException("更新进化阶段失败", ResultCode.GLOBAL_ERROR); logger.LogInformation("更新进化阶段成功,Id: {Id}", id); return BuildEvolutionOutput(evolution); @@ -774,13 +774,13 @@ public class PetService( { var evolution = await petEvolutionRepository.GetByIdAsync(id); if (evolution == null || evolution.IsDeleted) - throw new BusinessException("进化阶段不存在", 404); + throw new BusinessException("进化阶段不存在", ResultCode.NOT_FOUND); // 校验是否有用户宠物处于该形态 var hasUserPet = petRepository.Context.Queryable() .Any(p => p.CurrentEvolutionId == id && !p.IsDeleted); if (hasUserPet) - throw new BusinessException("有用户宠物正处于该形态,无法删除", 400); + throw new BusinessException("有用户宠物正处于该形态,无法删除", ResultCode.BAD_REQUEST); evolution.IsDeleted = true; evolution.UpdatedBy = "System"; @@ -797,7 +797,7 @@ public class PetService( { var evolution = await petEvolutionRepository.GetByIdAsync(id); if (evolution == null || evolution.IsDeleted) - throw new BusinessException("进化阶段不存在", 404); + throw new BusinessException("进化阶段不存在", ResultCode.NOT_FOUND); return BuildEvolutionOutput(evolution); } @@ -861,16 +861,16 @@ public class PetService( public async Task CreateSkinAsync(PetSkinInput input) { if (input.TemplateId <= 0) - throw new BusinessException("模板Id不能为空", 400); + throw new BusinessException("模板Id不能为空", ResultCode.BAD_REQUEST); if (string.IsNullOrWhiteSpace(input.Name)) - throw new BusinessException("皮肤名称不能为空", 400); + throw new BusinessException("皮肤名称不能为空", ResultCode.BAD_REQUEST); // 校验模板是否存在 var templateExists = petTemplateRepository.Context.Queryable() .Any(t => t.Id == input.TemplateId && !t.IsDeleted); if (!templateExists) - throw new BusinessException("宠物模板不存在", 404); + throw new BusinessException("宠物模板不存在", ResultCode.NOT_FOUND); var skin = new PetSkin { @@ -890,7 +890,7 @@ public class PetService( var result = await petSkinRepository.InsertAsync(skin); if (!result) - throw new BusinessException("创建皮肤失败", 500); + throw new BusinessException("创建皮肤失败", ResultCode.GLOBAL_ERROR); // 搬运封面图到正式目录 if (OssImageHelper.IsTempImage(skin.CoverImageUrl)) @@ -911,10 +911,10 @@ public class PetService( { var skin = await petSkinRepository.GetByIdAsync(id); if (skin == null || skin.IsDeleted) - throw new BusinessException("皮肤不存在", 404); + throw new BusinessException("皮肤不存在", ResultCode.NOT_FOUND); if (string.IsNullOrWhiteSpace(input.Name)) - throw new BusinessException("皮肤名称不能为空", 400); + throw new BusinessException("皮肤名称不能为空", ResultCode.BAD_REQUEST); skin.TemplateId = input.TemplateId; skin.Name = input.Name.Trim(); @@ -937,7 +937,7 @@ public class PetService( var result = await petSkinRepository.UpdateAsync(skin); if (!result) - throw new BusinessException("更新皮肤失败", 500); + throw new BusinessException("更新皮肤失败", ResultCode.GLOBAL_ERROR); logger.LogInformation("更新皮肤成功,Id: {Id}", id); @@ -957,13 +957,13 @@ public class PetService( { var skin = await petSkinRepository.GetByIdAsync(id); if (skin == null || skin.IsDeleted) - throw new BusinessException("皮肤不存在", 404); + throw new BusinessException("皮肤不存在", ResultCode.NOT_FOUND); // 校验是否有用户宠物正在使用该皮肤 var inUse = petRepository.Context.Queryable() .Any(p => p.CurrentSkinId == id && !p.IsDeleted); if (inUse) - throw new BusinessException("有用户宠物正在使用该皮肤,无法删除", 400); + throw new BusinessException("有用户宠物正在使用该皮肤,无法删除", ResultCode.BAD_REQUEST); skin.IsDeleted = true; skin.UpdatedBy = "System"; @@ -980,7 +980,7 @@ public class PetService( { var skin = await petSkinRepository.GetByIdAsync(id); if (skin == null || skin.IsDeleted) - throw new BusinessException("皮肤不存在", 404); + throw new BusinessException("皮肤不存在", ResultCode.NOT_FOUND); var images = await petSkinImageRepository.Queryable() .Where(i => i.SkinId == id && !i.IsDeleted) @@ -1072,19 +1072,19 @@ public class PetService( public async Task CreateSkinImageAsync(PetSkinImageInput input) { if (input.SkinId <= 0) - throw new BusinessException("皮肤Id不能为空", 400); + throw new BusinessException("皮肤Id不能为空", ResultCode.BAD_REQUEST); if (input.EvolutionStageId <= 0) - throw new BusinessException("进化阶段Id不能为空", 400); + throw new BusinessException("进化阶段Id不能为空", ResultCode.BAD_REQUEST); if (string.IsNullOrWhiteSpace(input.ImageUrl)) - throw new BusinessException("图片地址不能为空", 400); + throw new BusinessException("图片地址不能为空", ResultCode.BAD_REQUEST); // 校验皮肤是否存在 var skinExists = petSkinRepository.Context.Queryable() .Any(s => s.Id == input.SkinId && !s.IsDeleted); if (!skinExists) - throw new BusinessException("皮肤不存在", 404); + throw new BusinessException("皮肤不存在", ResultCode.NOT_FOUND); var image = new PetSkinImage { @@ -1102,7 +1102,7 @@ public class PetService( var result = await petSkinImageRepository.InsertAsync(image); if (!result) - throw new BusinessException("创建皮肤图片失败", 500); + throw new BusinessException("创建皮肤图片失败", ResultCode.GLOBAL_ERROR); // 搬运图片到正式目录 if (OssImageHelper.IsTempImage(image.ImageUrl)) @@ -1123,10 +1123,10 @@ public class PetService( { var image = await petSkinImageRepository.GetByIdAsync(id); if (image == null || image.IsDeleted) - throw new BusinessException("皮肤图片不存在", 404); + throw new BusinessException("皮肤图片不存在", ResultCode.NOT_FOUND); if (string.IsNullOrWhiteSpace(input.ImageUrl)) - throw new BusinessException("图片地址不能为空", 400); + throw new BusinessException("图片地址不能为空", ResultCode.BAD_REQUEST); image.SkinId = input.SkinId; image.EvolutionStageId = input.EvolutionStageId; @@ -1147,7 +1147,7 @@ public class PetService( var result = await petSkinImageRepository.UpdateAsync(image); if (!result) - throw new BusinessException("更新皮肤图片失败", 500); + throw new BusinessException("更新皮肤图片失败", ResultCode.GLOBAL_ERROR); logger.LogInformation("更新皮肤图片成功,Id: {Id}", id); return BuildSkinImageOutput(image); @@ -1160,7 +1160,7 @@ public class PetService( { var image = await petSkinImageRepository.GetByIdAsync(id); if (image == null || image.IsDeleted) - throw new BusinessException("皮肤图片不存在", 404); + throw new BusinessException("皮肤图片不存在", ResultCode.NOT_FOUND); image.IsDeleted = true; image.UpdatedBy = "System"; @@ -1208,7 +1208,7 @@ public class PetService( public async Task> GetEvolutionsByTemplateIdAsync(long templateId) { if (templateId <= 0) - throw new BusinessException("模板Id不能为空", 400); + throw new BusinessException("模板Id不能为空", ResultCode.BAD_REQUEST); var list = await petEvolutionRepository.Queryable() .Where(e => e.TemplateId == templateId && !e.IsDeleted) @@ -1224,7 +1224,7 @@ public class PetService( public async Task> GetSkinsByTemplateIdAsync(long templateId) { if (templateId <= 0) - throw new BusinessException("模板Id不能为空", 400); + throw new BusinessException("模板Id不能为空", ResultCode.BAD_REQUEST); var list = await petSkinRepository.Queryable() .Where(s => s.TemplateId == templateId && !s.IsDeleted) @@ -1276,12 +1276,12 @@ public class PetService( public async Task> GetSkinImagesGroupedBySkinIdAsync(long skinId) { if (skinId <= 0) - throw new BusinessException("皮肤Id不能为空", 400); + throw new BusinessException("皮肤Id不能为空", ResultCode.BAD_REQUEST); // 1. 获取皮肤信息 var skin = await petSkinRepository.GetByIdAsync(skinId); if (skin == null || skin.IsDeleted) - throw new BusinessException("皮肤不存在", 404); + throw new BusinessException("皮肤不存在", ResultCode.NOT_FOUND); // 2. 获取该模板的所有进化阶段(按阶段等级排序) var evolutions = await petEvolutionRepository.Queryable() diff --git a/QYZH.InteractiveMagazine.Service/PointsService.cs b/QYZH.InteractiveMagazine.Service/PointsService.cs index 5cd73a9..fe2a29f 100644 --- a/QYZH.InteractiveMagazine.Service/PointsService.cs +++ b/QYZH.InteractiveMagazine.Service/PointsService.cs @@ -28,7 +28,7 @@ public class PointsService( input.UserId, input.Amount, input.ChangeType); if (input.Amount <= 0) - throw new BusinessException("增加积分数量必须大于0", 400); + throw new BusinessException("增加积分数量必须大于0", ResultCode.BAD_REQUEST); AddPointsOutput result = null!; @@ -49,7 +49,7 @@ public class PointsService( input.UserId, input.Amount, input.ChangeType); if (input.Amount <= 0) - throw new BusinessException("扣除积分数量必须大于0", 400); + throw new BusinessException("扣除积分数量必须大于0", ResultCode.BAD_REQUEST); DeductPointsOutput result = null!; @@ -71,7 +71,7 @@ public class PointsService( public async Task AddPointsInTranAsync(AddPointsInput input) { if (input.Amount <= 0) - throw new BusinessException("增加积分数量必须大于0", 400); + throw new BusinessException("增加积分数量必须大于0", ResultCode.BAD_REQUEST); // 查询用户当前积分 var user = await Context.Queryable() @@ -79,7 +79,7 @@ public class PointsService( .FirstAsync(); if (user == null) - throw new BusinessException("用户不存在", 404); + throw new BusinessException("用户不存在", ResultCode.NOT_FOUND); var previousBalance = user.Points; var newBalance = previousBalance + input.Amount; @@ -129,7 +129,7 @@ public class PointsService( public async Task DeductPointsInTranAsync(DeductPointsInput input) { if (input.Amount <= 0) - throw new BusinessException("扣除积分数量必须大于0", 400); + throw new BusinessException("扣除积分数量必须大于0", ResultCode.BAD_REQUEST); // 查询用户当前积分 var user = await Context.Queryable() @@ -137,13 +137,13 @@ public class PointsService( .FirstAsync(); if (user == null) - throw new BusinessException("用户不存在", 404); + throw new BusinessException("用户不存在", ResultCode.NOT_FOUND); var previousBalance = user.Points; // 余额不足校验 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; @@ -214,7 +214,7 @@ public class PointsService( .FirstAsync(); if (user == null) - throw new BusinessException("用户不存在", 404); + throw new BusinessException("用户不存在", ResultCode.NOT_FOUND); // 查询累计收入(Income 类型) var totalIncome = await Context.Queryable() @@ -241,10 +241,10 @@ public class PointsService( public async Task> GetPointsRecordsAsync(PointsRecordQueryInput input) { if (input.PageIndex <= 0) - throw new BusinessException("页码必须大于0", 400); + throw new BusinessException("页码必须大于0", ResultCode.BAD_REQUEST); 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() .Where(r => r.UserId == input.UserId && !r.IsDeleted) diff --git a/QYZH.InteractiveMagazine.Service/ProductService.cs b/QYZH.InteractiveMagazine.Service/ProductService.cs index f75679f..a19e021 100644 --- a/QYZH.InteractiveMagazine.Service/ProductService.cs +++ b/QYZH.InteractiveMagazine.Service/ProductService.cs @@ -29,17 +29,17 @@ public class ProductService( if (string.IsNullOrWhiteSpace(input.Name)) { - throw new BusinessException("商品名称不能为空", 400); + throw new BusinessException("商品名称不能为空", ResultCode.BAD_REQUEST); } if (string.IsNullOrWhiteSpace(input.Type)) { - throw new BusinessException("商品类型不能为空", 400); + throw new BusinessException("商品类型不能为空", ResultCode.BAD_REQUEST); } if (input.Price < 0) { - throw new BusinessException("商品价格不能为负数", 400); + throw new BusinessException("商品价格不能为负数", ResultCode.BAD_REQUEST); } var product = new Product @@ -66,7 +66,7 @@ public class ProductService( if (!result) { logger.LogError("商品创建失败,商品名称: {Name}", input.Name); - throw new BusinessException("创建商品失败", 500); + throw new BusinessException("创建商品失败", ResultCode.GLOBAL_ERROR); } // 将 temp 目录下的图片搬运到正式目录 @@ -113,22 +113,22 @@ public class ProductService( if (product == null) { logger.LogWarning("未找到要更新的商品,ID: {Id}", id); - throw new BusinessException("商品不存在", 404); + throw new BusinessException("商品不存在", ResultCode.NOT_FOUND); } if (string.IsNullOrWhiteSpace(input.Name)) { - throw new BusinessException("商品名称不能为空", 400); + throw new BusinessException("商品名称不能为空", ResultCode.BAD_REQUEST); } if (string.IsNullOrWhiteSpace(input.Type)) { - throw new BusinessException("商品类型不能为空", 400); + throw new BusinessException("商品类型不能为空", ResultCode.BAD_REQUEST); } if (input.Price < 0) { - throw new BusinessException("商品价格不能为负数", 400); + throw new BusinessException("商品价格不能为负数", ResultCode.BAD_REQUEST); } // 将 temp 目录下的新图片搬运到正式目录 @@ -158,7 +158,7 @@ public class ProductService( if (!result) { logger.LogError("商品更新失败,ID: {Id}", id); - throw new BusinessException("更新商品失败", 500); + throw new BusinessException("更新商品失败", ResultCode.GLOBAL_ERROR); } logger.LogInformation("商品更新成功,ID: {Id}", id); @@ -195,14 +195,14 @@ public class ProductService( if (product == null) { logger.LogWarning("未找到要删除的商品,ID: {Id}", id); - throw new BusinessException("商品不存在", 404); + throw new BusinessException("商品不存在", ResultCode.NOT_FOUND); } var result = await productRepository.DeleteByIdAsync(id); if (!result) { logger.LogError("商品删除失败,ID: {Id}", id); - throw new BusinessException("删除商品失败", 500); + throw new BusinessException("删除商品失败", ResultCode.GLOBAL_ERROR); } logger.LogInformation("商品删除成功,ID: {Id}", id); @@ -219,7 +219,7 @@ public class ProductService( if (product == null) { logger.LogWarning("未找到商品,ID: {Id}", id); - throw new BusinessException("商品不存在", 404); + throw new BusinessException("商品不存在", ResultCode.NOT_FOUND); } return new ProductOutput @@ -252,12 +252,12 @@ public class ProductService( if (input.PageIndex <= 0) { - throw new BusinessException("页码必须大于0", 400); + throw new BusinessException("页码必须大于0", ResultCode.BAD_REQUEST); } if (input.PageSize <= 0 || input.PageSize > 100) { - throw new BusinessException("每页条数必须在1-100之间", 400); + throw new BusinessException("每页条数必须在1-100之间", ResultCode.BAD_REQUEST); } RefAsync totalNumber = 0; @@ -303,7 +303,7 @@ public class ProductService( if (product == null) { logger.LogWarning("未找到要更新状态的商品,ID: {Id}", id); - throw new BusinessException("商品不存在", 404); + throw new BusinessException("商品不存在", ResultCode.NOT_FOUND); } product.Status = product.Status == (int)ProductStatusEnum.OnSale @@ -316,7 +316,7 @@ public class ProductService( if (!result) { logger.LogError("商品状态更新失败,ID: {Id}", id); - throw new BusinessException("更新商品状态失败", 500); + throw new BusinessException("更新商品状态失败", ResultCode.GLOBAL_ERROR); } logger.LogInformation("商品上下架状态更新成功,ID: {Id}, SaleStatus: {SaleStatus}", id, product.Status); diff --git a/QYZH.InteractiveMagazine.Service/UserAnswerTaskService.cs b/QYZH.InteractiveMagazine.Service/UserAnswerTaskService.cs index c5a832f..218eeae 100644 --- a/QYZH.InteractiveMagazine.Service/UserAnswerTaskService.cs +++ b/QYZH.InteractiveMagazine.Service/UserAnswerTaskService.cs @@ -1,6 +1,7 @@ using Microsoft.Extensions.Logging; using QYZH.InteractiveMagazine.IService; using QYZH.InteractiveMagazine.Models.Common; +using QYZH.InteractiveMagazine.Models.Dto; using QYZH.InteractiveMagazine.Models.Dto.Points; using QYZH.InteractiveMagazine.Models.Dto.UserAnswerTaskService; using QYZH.InteractiveMagazine.Models.Entity; @@ -939,7 +940,7 @@ public class UserAnswerTaskService( 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) { - 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); if (completedAnswer == null) { - throw new BusinessException("跨页题目需要完成所有任务才能领取积分", 400); + throw new BusinessException("跨页题目需要完成所有任务才能领取积分", ResultCode.BAD_REQUEST); } } } @@ -997,7 +998,7 @@ public class UserAnswerTaskService( // 普通题目:只需要 Status=1 即可 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) { - throw new BusinessException("该任务无积分可领取", 400); + throw new BusinessException("该任务无积分可领取", ResultCode.BAD_REQUEST); } // ============================================ @@ -1054,7 +1055,7 @@ public class UserAnswerTaskService( 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) { - throw new BusinessException("任务分组Id列表不能为空", 400); + throw new BusinessException("任务分组Id列表不能为空", ResultCode.BAD_REQUEST); } var groupIds = input.GroupIds.Distinct().ToList(); diff --git a/QYZH.InteractiveMagazine.Service/UserJournalService.cs b/QYZH.InteractiveMagazine.Service/UserJournalService.cs index 15cd79c..f69a97b 100644 --- a/QYZH.InteractiveMagazine.Service/UserJournalService.cs +++ b/QYZH.InteractiveMagazine.Service/UserJournalService.cs @@ -31,14 +31,14 @@ public class UserJournalService( // 校验参数 if (input.JournalId <= 0|| input.Id <= 0) { - throw new BusinessException("参数错误,未获取到期刊", 400); + throw new BusinessException("参数错误,未获取到期刊", ResultCode.BAD_REQUEST); } // 校验用户是否存在 var user = await usersRepository.GetByIdAsync(userId); if (user == null || user.IsDeleted) { 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) { logger.LogWarning("绑定期刊失败,期刊不存在,JournalId: {JournalId}", input.JournalId); - throw new BusinessException("期刊不存在", 404); + throw new BusinessException("期刊不存在", ResultCode.NOT_FOUND); } // 校验期刊状态 if (journal.Status != (int)JournalStatusEnum.Published) { 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) { 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) { 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); @@ -129,12 +129,12 @@ public class UserJournalService( if (input.PageIndex <= 0) { - throw new BusinessException("页码必须大于0", 400); + throw new BusinessException("页码必须大于0", ResultCode.BAD_REQUEST); } if (input.PageSize <= 0 || input.PageSize > 100) { - throw new BusinessException("每页条数必须在1-100之间", 400); + throw new BusinessException("每页条数必须在1-100之间", ResultCode.BAD_REQUEST); } RefAsync totalNumber = 0; @@ -167,21 +167,21 @@ public class UserJournalService( if (userJournal == null || userJournal.IsDeleted) { logger.LogWarning("取消绑定失败,记录不存在,Id: {Id}", id); - throw new BusinessException("绑定记录不存在", 404); + throw new BusinessException("绑定记录不存在", ResultCode.NOT_FOUND); } // 校验归属权:只能取消自己的绑定 if (userJournal.UserId != 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); if (!result) { logger.LogError("取消绑定失败,Id: {Id}", id); - throw new BusinessException("取消绑定失败,请稍后重试", 500); + throw new BusinessException("取消绑定失败,请稍后重试", ResultCode.GLOBAL_ERROR); } logger.LogInformation("取消期刊绑定成功,UserId: {UserId}, Id: {Id}", userId, id); diff --git a/QYZH.InteractiveMagazine.Service/UsersService.cs b/QYZH.InteractiveMagazine.Service/UsersService.cs index 98e30c4..f7f3ea6 100644 --- a/QYZH.InteractiveMagazine.Service/UsersService.cs +++ b/QYZH.InteractiveMagazine.Service/UsersService.cs @@ -197,7 +197,7 @@ public class UsersService( // 校验用户是否存在 var user = await Queryable().Where(u => u.Id == userId && !u.IsDeleted).FirstAsync(); if (user == null) - throw new BusinessException("用户不存在", 404); + throw new BusinessException("用户不存在", ResultCode.NOT_FOUND); // 调用积分服务增加积分 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(); if (user == null) - throw new BusinessException("用户不存在", 404); + throw new BusinessException("用户不存在", ResultCode.NOT_FOUND); // 调用积分服务扣除积分 var result = await pointsService.DeductPointsAsync(new DeductPointsInput diff --git a/QYZH.InteractiveMagazine.Service/WeChatAuthService.cs b/QYZH.InteractiveMagazine.Service/WeChatAuthService.cs index 86e37e1..3693116 100644 --- a/QYZH.InteractiveMagazine.Service/WeChatAuthService.cs +++ b/QYZH.InteractiveMagazine.Service/WeChatAuthService.cs @@ -4,6 +4,7 @@ using QYZH.InteractiveMagazine.Common.Helpers; using QYZH.InteractiveMagazine.Infrastructure.Auth; using QYZH.InteractiveMagazine.IService; using QYZH.InteractiveMagazine.Models.Common; +using QYZH.InteractiveMagazine.Models.Dto; using QYZH.InteractiveMagazine.Models.Entity; using QYZH.InteractiveMagazine.Models.Enum; using QYZH.InteractiveMagazine.Models.Settings; @@ -38,7 +39,7 @@ public class WeChatAuthService( logger.LogInformation("微信小程序登录"); if (string.IsNullOrWhiteSpace(input.Code)) - throw new BusinessException("微信登录凭证 code 不能为空", 400); + throw new BusinessException("微信登录凭证 code 不能为空", ResultCode.BAD_REQUEST); var weChatSettings = GetWeChatSettings(); @@ -48,7 +49,7 @@ public class WeChatAuthService( { var errMsg = wxResponse?.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); @@ -130,7 +131,7 @@ public class WeChatAuthService( logger.LogInformation("微信快捷登录,OpenId: {OpenId}", 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() .Where(w => w.OpenId == input.OpenId && !w.IsDeleted) @@ -139,7 +140,7 @@ public class WeChatAuthService( if (wxUser == null) { logger.LogWarning("快捷登录失败,OpenId: {OpenId} 下无 WxUser", input.OpenId); - throw new BusinessException("未找到该微信账号关联的用户,请先完成注册", 404); + throw new BusinessException("未找到该微信账号关联的用户,请先完成注册", ResultCode.NOT_FOUND); } var users = await wxUserRepository.Context.Queryable() @@ -165,17 +166,17 @@ public class WeChatAuthService( .FirstAsync(); if (targetUser == null) - throw new BusinessException("目标用户不存在", 404); + throw new BusinessException("目标用户不存在", ResultCode.NOT_FOUND); // 校验目标用户属于同一 WxUser if (targetUser.WxUserId != wxUserId) { logger.LogWarning("切换用户失败,WxUserId 不匹配,当前: {Current}, 目标: {Target}", wxUserId, targetUser.WxUserId); - throw new BusinessException("无法切换到该用户", 403); + throw new BusinessException("无法切换到该用户", ResultCode.FORBIDDEN); } if (targetUser.Status == (int)UserStatusEnum.Disabled) - throw new BusinessException("目标账号已被禁用", 403); + throw new BusinessException("目标账号已被禁用", ResultCode.FORBIDDEN); // 更新 IsLastOnline(清除所有,设置目标为 true) await wxUserRepository.Context.Updateable() @@ -232,7 +233,7 @@ public class WeChatAuthService( logger.LogInformation("新增用户,WxUserId: {WxUserId}, Name: {Name}", wxUserId, input.Name); if (string.IsNullOrWhiteSpace(input.Name)) - throw new BusinessException("昵称不能为空", 400); + throw new BusinessException("昵称不能为空", ResultCode.BAD_REQUEST); // 校验 WxUser 是否存在 var wxUser = await wxUserRepository.Context.Queryable() @@ -240,7 +241,7 @@ public class WeChatAuthService( .FirstAsync(); if (wxUser == null) - throw new BusinessException("微信用户不存在", 404); + throw new BusinessException("微信用户不存在", ResultCode.NOT_FOUND); // 创建新用户 var newUser = new Users @@ -280,14 +281,14 @@ public class WeChatAuthService( logger.LogInformation("修改家长名字,WxUserId: {WxUserId}, NewName: {Name}", wxUserId, input.Name); if (string.IsNullOrWhiteSpace(input.Name)) - throw new BusinessException("名字不能为空", 400); + throw new BusinessException("名字不能为空", ResultCode.BAD_REQUEST); var wxUser = await wxUserRepository.Context.Queryable() .Where(w => w.Id == wxUserId && !w.IsDeleted) .FirstAsync(); if (wxUser == null) - throw new BusinessException("微信用户不存在", 404); + throw new BusinessException("微信用户不存在", ResultCode.NOT_FOUND); await wxUserRepository.Context.Updateable() .SetColumns(w => w.Name == input.Name.Trim()) @@ -358,7 +359,7 @@ public class WeChatAuthService( catch (Exception ex) { 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 ?? "未知错误"; 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; @@ -441,7 +442,7 @@ public class WeChatAuthService( if (settings == null || string.IsNullOrWhiteSpace(settings.AppId) || string.IsNullOrWhiteSpace(settings.AppSecret)) { logger.LogError("微信配置不完整,请检查 appsettings.json 中的 WeChatSettings 节点"); - throw new BusinessException("微信配置不完整,请联系系统管理员", 500); + throw new BusinessException("微信配置不完整,请联系系统管理员", ResultCode.GLOBAL_ERROR); } return settings; } @@ -458,7 +459,7 @@ public class WeChatAuthService( }; if (string.IsNullOrWhiteSpace(jwtSettings.SecretKey)) - throw new BusinessException("JWT 配置不完整", 500); + throw new BusinessException("JWT 配置不完整", ResultCode.GLOBAL_ERROR); return jwtSettings; } diff --git a/QYZH.InteractiveMagazine.Service/WeChatCommunityService.cs b/QYZH.InteractiveMagazine.Service/WeChatCommunityService.cs index 1566514..28c563c 100644 --- a/QYZH.InteractiveMagazine.Service/WeChatCommunityService.cs +++ b/QYZH.InteractiveMagazine.Service/WeChatCommunityService.cs @@ -116,13 +116,13 @@ public class WeChatCommunityService( if (input.MessageId <= 0) { - throw new BusinessException("消息ID无效", 400); + throw new BusinessException("消息ID无效", ResultCode.BAD_REQUEST); } var message = await messageRepository.GetByIdAsync(input.MessageId); if (message == null) { - throw new BusinessException("消息不存在", 404); + throw new BusinessException("消息不存在", ResultCode.NOT_FOUND); } // 检查是否已点赞 @@ -132,7 +132,7 @@ public class WeChatCommunityService( 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(); if (insertResult <= 0) { - throw new BusinessException("点赞失败", 500); + throw new BusinessException("点赞失败", ResultCode.GLOBAL_ERROR); } // 更新点赞数 @@ -183,13 +183,13 @@ public class WeChatCommunityService( if (messageId <= 0) { - throw new BusinessException("消息ID无效", 400); + throw new BusinessException("消息ID无效", ResultCode.BAD_REQUEST); } var message = await messageRepository.GetByIdAsync(messageId); if (message == null) { - throw new BusinessException("消息不存在", 404); + throw new BusinessException("消息不存在", ResultCode.NOT_FOUND); } var existingLike = await Context.Queryable() @@ -198,7 +198,7 @@ public class WeChatCommunityService( if (existingLike == null) { - throw new BusinessException("您尚未点赞过该消息", 400); + throw new BusinessException("您尚未点赞过该消息", ResultCode.BAD_REQUEST); } // 软删除点赞记录 diff --git a/QYZH.InteractiveMagazine.Service/WxMallService.cs b/QYZH.InteractiveMagazine.Service/WxMallService.cs index 1ee9d00..bf0b5eb 100644 --- a/QYZH.InteractiveMagazine.Service/WxMallService.cs +++ b/QYZH.InteractiveMagazine.Service/WxMallService.cs @@ -1,6 +1,7 @@ using Microsoft.Extensions.Logging; using QYZH.InteractiveMagazine.IService; using QYZH.InteractiveMagazine.Models.Common; +using QYZH.InteractiveMagazine.Models.Dto; using QYZH.InteractiveMagazine.Models.Dto.Bag; using QYZH.InteractiveMagazine.Models.Dto.Mall; using QYZH.InteractiveMagazine.Models.Dto.Points; @@ -187,10 +188,10 @@ public class WxMallService( userId, input.ProductId, input.Quantity); if (input.ProductId <= 0) - throw new BusinessException("商品Id无效", 400); + throw new BusinessException("商品Id无效", ResultCode.BAD_REQUEST); if (input.Quantity <= 0) - throw new BusinessException("兑换数量必须大于0", 400); + throw new BusinessException("兑换数量必须大于0", ResultCode.BAD_REQUEST); // 查询商品 var product = await exchangeRecordRepository.Context.Queryable() @@ -198,7 +199,7 @@ public class WxMallService( .FirstAsync(); if (product == null) - throw new BusinessException("商品不存在或已下架", 404); + throw new BusinessException("商品不存在或已下架", ResultCode.NOT_FOUND); var totalCost = product.Price * input.Quantity; @@ -404,24 +405,24 @@ public class WxMallService( logger.LogInformation("使用背包物品,UserId: {UserId}, BagItemId: {BagItemId}", userId, input.BagItemId); if (input.BagItemId <= 0) - throw new BusinessException("背包物品Id无效", 400); + throw new BusinessException("背包物品Id无效", ResultCode.BAD_REQUEST); var bagItem = await exchangeRecordRepository.Context.Queryable() .Where(b => b.Id == input.BagItemId && b.UserId == userId && b.Status == (int)UserBagStatusEnum.Available) .FirstAsync(); if (bagItem == null) - throw new BusinessException("背包物品不存在", 404); + throw new BusinessException("背包物品不存在", ResultCode.NOT_FOUND); if (bagItem.Quantity <= 0) - throw new BusinessException("物品数量不足", 400); + throw new BusinessException("物品数量不足", ResultCode.BAD_REQUEST); switch (bagItem.ItemType) { case "MakeUpCard": return await UseMakeUpCardAsync(userId, bagItem, input); 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 UseMakeUpCardAsync(long userId, UserBag bagItem, UseItemInput input) { if (string.IsNullOrEmpty(input.TargetDate)) - throw new BusinessException("请指定补签日期", 400); + throw new BusinessException("请指定补签日期", ResultCode.BAD_REQUEST); if (!DateTime.TryParse(input.TargetDate, out var targetDate)) - throw new BusinessException("日期格式无效", 400); + throw new BusinessException("日期格式无效", ResultCode.BAD_REQUEST); targetDate = targetDate.Date; if (targetDate >= DateTime.Now.Date) - throw new BusinessException("只能补签过去的日期", 400); + throw new BusinessException("只能补签过去的日期", ResultCode.BAD_REQUEST); // 调用签到服务执行补签(内部会检查并扣减补签卡) var checkInResult = await checkInService.MakeUpCheckInAsync(userId, targetDate); @@ -467,7 +468,7 @@ public class WxMallService( .FirstAsync(); if (pet == null) - throw new BusinessException("您还没有宠物", 404); + throw new BusinessException("您还没有宠物", ResultCode.NOT_FOUND); if (input.SkinId == 0) { @@ -488,7 +489,7 @@ public class WxMallService( .FirstAsync(); if (skin == null) - throw new BusinessException("皮肤不存在", 404); + throw new BusinessException("皮肤不存在", ResultCode.NOT_FOUND); // 校验背包中是否拥有该皮肤(通过 MetaData 中的 SkinId 判断) var hasSkin = await exchangeRecordRepository.Context.Queryable() @@ -499,7 +500,7 @@ public class WxMallService( var owned = hasSkin.Any(b => GetSkinIdFromMetaData(b.MetaData) == input.SkinId); if (!owned) - throw new BusinessException("您尚未拥有该皮肤,请先兑换", 400); + throw new BusinessException("您尚未拥有该皮肤,请先兑换", ResultCode.BAD_REQUEST); // 换肤 await exchangeRecordRepository.Context.Updateable() diff --git a/QYZH.InteractiveMagazine.WebApi/Controllers/BaseController.cs b/QYZH.InteractiveMagazine.WebApi/Controllers/BaseController.cs index 0788b80..58d9117 100644 --- a/QYZH.InteractiveMagazine.WebApi/Controllers/BaseController.cs +++ b/QYZH.InteractiveMagazine.WebApi/Controllers/BaseController.cs @@ -62,7 +62,10 @@ public abstract class BaseController : ControllerBase /// 统一响应对象 protected BaseResponse Fail(string message, int code = 500) { - return BaseResponse.Fail(ResultCode.GLOBAL_ERROR, message); + var resultCode = Enum.IsDefined(typeof(ResultCode), code) + ? (ResultCode)code + : ResultCode.GLOBAL_ERROR; + return BaseResponse.Fail(resultCode, message); } protected IActionResult ApiResult(bool success, string msg) @@ -91,7 +94,7 @@ public abstract class BaseController : ControllerBase //var webHostEnvironment = App.WebHostEnvironment; if (!Path.Exists(path)) { - throw new BusinessException(fileName + "文件不存在"); + throw new BusinessException(fileName + "文件不存在", ResultCode.NOT_FOUND); } var stream = System.IO.File.OpenRead(path); //创建文件流 diff --git a/QYZH.InteractiveMagazine.WebApi/Controllers/JournalController.cs b/QYZH.InteractiveMagazine.WebApi/Controllers/JournalController.cs index 2ba3b25..8d2b452 100644 --- a/QYZH.InteractiveMagazine.WebApi/Controllers/JournalController.cs +++ b/QYZH.InteractiveMagazine.WebApi/Controllers/JournalController.cs @@ -395,15 +395,15 @@ namespace QYZH.InteractiveMagazine.WebApi.Controllers { var entity = await JournalService.GetFirstAsync(x => x.Id == JournalId); if (entity == null) - throw new BusinessException("书籍不存在"); + throw new BusinessException("书籍不存在", ResultCode.NOT_FOUND); var downloadUrl = entity.DownloadJournalPagePdfName; if (string.IsNullOrWhiteSpace(downloadUrl)) - throw new BusinessException("下载点阵码PDF文件为空,请先铺码"); + throw new BusinessException("下载点阵码PDF文件为空,请先铺码", ResultCode.BAD_REQUEST); var stream = await httpClientFactory.CreateClient().GetStreamAsync(downloadUrl); //创建文件流 if (stream == null) - throw new BusinessException("下载点阵码PDF文件失败"); + throw new BusinessException("下载点阵码PDF文件失败", ResultCode.GLOBAL_ERROR); Response.Headers.Append("Access-Control-Expose-Headers", "Content-Disposition"); diff --git a/QYZH.InteractiveMagazine.WorkService/Consumers/AutoDotCodeConsumer.cs b/QYZH.InteractiveMagazine.WorkService/Consumers/AutoDotCodeConsumer.cs index 819fe15..7d3e038 100644 --- a/QYZH.InteractiveMagazine.WorkService/Consumers/AutoDotCodeConsumer.cs +++ b/QYZH.InteractiveMagazine.WorkService/Consumers/AutoDotCodeConsumer.cs @@ -1,4 +1,5 @@ using Newtonsoft.Json; +using QYZH.InteractiveMagazine.Common.Extensions; using QYZH.InteractiveMagazine.Infrastructure.OSS; using QYZH.InteractiveMagazine.Models.Dto.Journal; using QYZH.InteractiveMagazine.Models.Entity; @@ -65,7 +66,19 @@ public class AutoDotCodeConsumer(IConfiguration configuration, var uploadFilePath = uploadPdfDic + uploadFileName; // 获取上传成功的书籍页码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)) { diff --git a/QYZH.InteractiveMagazine.WorkService/Consumers/JournalTaskReceiveConsumer.cs b/QYZH.InteractiveMagazine.WorkService/Consumers/JournalTaskReceiveConsumer.cs index 5f76e8d..a44f653 100644 --- a/QYZH.InteractiveMagazine.WorkService/Consumers/JournalTaskReceiveConsumer.cs +++ b/QYZH.InteractiveMagazine.WorkService/Consumers/JournalTaskReceiveConsumer.cs @@ -1,18 +1,21 @@ +using Newtonsoft.Json; +using QYZH.InteractiveMagazine.Infrastructure.OSS; +using SqlSugar; using System.Text; +using System.Threading.Channels; +using Yitter.IdGenerator; namespace QYZH.InteractiveMagazine.WorkService.Consumers; /// /// 期刊任务接收消费者(示例) /// -public class JournalTaskReceiveConsumer : IQueueConsumer +public class JournalTaskReceiveConsumer(ILogger logger, IConfiguration configuration, + IServiceScopeFactory scopeFactory, + IWebHostEnvironment webHostEnvironment, + IHttpClientFactory httpClientFactory, + OssService ossService) : IQueueConsumer { - private readonly ILogger _logger; - - public JournalTaskReceiveConsumer(ILogger logger) - { - _logger = logger; - } public string Exchange => "ex.journal"; @@ -20,20 +23,63 @@ public class JournalTaskReceiveConsumer : IQueueConsumer 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); - _logger.LogInformation("收到期刊任务消息: {Message}", body); + var message = Encoding.UTF8.GetString(body); + logger.LogInformation("收到期刊任务消息: {Message}", message); + using var scope = scopeFactory.CreateScope(); + var client = scope.ServiceProvider.GetRequiredService(); // TODO: 在此编写具体的消息处理逻辑 + try + { + var data = System.Text.Json.JsonSerializer.Deserialize(message); + + + client.Ado.CommitTran(); + } + catch (Exception ex) + { + client.Ado.RollbackTran(); + logger.LogError(ex.Message + ex.StackTrace); + } await Task.CompletedTask; } - public Task OnErrorAsync(byte[] message, Exception exception) + public Task OnErrorAsync(byte[] body, Exception exception) { - var body = Encoding.UTF8.GetString(message); - _logger.LogError(exception, "处理期刊任务消息失败: {Message}", body); + var message = Encoding.UTF8.GetString(body); + logger.LogError(exception, "处理期刊任务消息失败: {Message}", message); 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 BreakTimes { get; set; } +} +public class BreakTime +{ + public DateTime Time { get; set; } + public long WaitTime { get; set; } +} \ No newline at end of file diff --git a/SqlMigrations/pet_module_optimization.sql b/SqlMigrations/pet_module_optimization.sql deleted file mode 100644 index 4424693..0000000 --- a/SqlMigrations/pet_module_optimization.sql +++ /dev/null @@ -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='宠物皮肤图片表';