重构项目结构,引入 Avalonia-Common、Avalonia-EFCore、Avalonia-Services,实现 API 与桌面端统一端点注册、过滤器、鉴权和标准响应格式。支持多数据库自动迁移与配置,集成 Serilog 日志系统。移除旧路由与控制器,提升接口一致性与可维护性。
177 lines
5.6 KiB
C#
177 lines
5.6 KiB
C#
using System.Text.Json.Serialization;
|
||
|
||
namespace Avalonia_Common.Core
|
||
{
|
||
/// <summary>
|
||
/// 统一 API 返回格式。
|
||
/// 所有接口的返回都包装为此格式,确保前端收到一致的数据结构。
|
||
/// </summary>
|
||
/// <typeparam name="T">业务数据类型</typeparam>
|
||
public class ApiResponse<T>
|
||
{
|
||
/// <summary>是否成功</summary>
|
||
[JsonPropertyName("success")]
|
||
public bool Success { get; set; }
|
||
|
||
/// <summary>HTTP 状态码</summary>
|
||
[JsonPropertyName("code")]
|
||
public int Code { get; set; }
|
||
|
||
/// <summary>消息(成功时可为 null,失败时包含错误描述)</summary>
|
||
[JsonPropertyName("message")]
|
||
public string? Message { get; set; }
|
||
|
||
/// <summary>业务数据</summary>
|
||
[JsonPropertyName("data")]
|
||
public T? Data { get; set; }
|
||
|
||
/// <summary>时间戳</summary>
|
||
[JsonPropertyName("timestamp")]
|
||
public DateTime Timestamp { get; set; } = DateTime.Now;
|
||
|
||
/// <summary>请求追踪 ID(用于排查问题)</summary>
|
||
[JsonPropertyName("traceId")]
|
||
public string? TraceId { get; set; }
|
||
|
||
// ---- 快捷工厂方法 ----
|
||
|
||
/// <summary>成功返回(有数据)</summary>
|
||
public static ApiResponse<T> Ok(T data, string? message = null)
|
||
{
|
||
return new ApiResponse<T>
|
||
{
|
||
Success = true,
|
||
Code = 200,
|
||
Message = message,
|
||
Data = data,
|
||
};
|
||
}
|
||
|
||
/// <summary>失败返回</summary>
|
||
public static ApiResponse<T> Fail(int code, string message, T? data = default)
|
||
{
|
||
return new ApiResponse<T>
|
||
{
|
||
Success = false,
|
||
Code = code,
|
||
Message = message,
|
||
Data = data,
|
||
};
|
||
}
|
||
|
||
/// <summary>400 参数错误</summary>
|
||
public static ApiResponse<T> BadRequest(string message = "参数错误")
|
||
=> Fail(400, message);
|
||
|
||
/// <summary>401 未授权</summary>
|
||
public static ApiResponse<T> Unauthorized(string message = "未授权")
|
||
=> Fail(401, message);
|
||
|
||
/// <summary>403 无权限</summary>
|
||
public static ApiResponse<T> Forbidden(string message = "无权限")
|
||
=> Fail(403, message);
|
||
|
||
/// <summary>404 未找到</summary>
|
||
public static ApiResponse<T> NotFound(string message = "资源不存在")
|
||
=> Fail(404, message);
|
||
|
||
/// <summary>500 服务器内部错误</summary>
|
||
public static ApiResponse<T> ServerError(string message = "服务器内部错误")
|
||
=> Fail(500, message);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 无数据的统一返回格式(object? 版本)。
|
||
/// </summary>
|
||
public class ApiResponse : ApiResponse<object?>
|
||
{
|
||
/// <summary>成功返回(无数据)</summary>
|
||
public static ApiResponse Succeed(string? message = null)
|
||
{
|
||
return new ApiResponse
|
||
{
|
||
Success = true,
|
||
Code = 200,
|
||
Message = message,
|
||
Data = null,
|
||
};
|
||
}
|
||
|
||
/// <summary>失败返回</summary>
|
||
public static ApiResponse Failure(int code, string message)
|
||
{
|
||
return new ApiResponse
|
||
{
|
||
Success = false,
|
||
Code = code,
|
||
Message = message,
|
||
Data = null,
|
||
};
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 分页返回格式
|
||
/// </summary>
|
||
public class PagedResponse<T>
|
||
{
|
||
[JsonPropertyName("success")]
|
||
public bool Success { get; set; } = true;
|
||
|
||
[JsonPropertyName("code")]
|
||
public int Code { get; set; } = 200;
|
||
|
||
[JsonPropertyName("items")]
|
||
public List<T> Items { get; set; } = new();
|
||
|
||
[JsonPropertyName("total")]
|
||
public int Total { get; set; }
|
||
|
||
[JsonPropertyName("page")]
|
||
public int Page { get; set; } = 1;
|
||
|
||
[JsonPropertyName("pageSize")]
|
||
public int PageSize { get; set; } = 20;
|
||
|
||
[JsonPropertyName("totalPages")]
|
||
public int TotalPages => PageSize > 0 ? (int)Math.Ceiling((double)Total / PageSize) : 0;
|
||
|
||
public static PagedResponse<T> From(List<T> items, int total, int page, int pageSize)
|
||
{
|
||
return new PagedResponse<T>
|
||
{
|
||
Items = items,
|
||
Total = total,
|
||
Page = page,
|
||
PageSize = pageSize,
|
||
};
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 端点返回辅助方法 —— 在 AppEndpoints 中快捷构建统一响应。
|
||
/// </summary>
|
||
public static class ResponseHelper
|
||
{
|
||
/// <summary>成功返回</summary>
|
||
public static ApiResponse<T> Ok<T>(T data, string? message = null)
|
||
=> ApiResponse<T>.Ok(data, message);
|
||
|
||
/// <summary>成功返回(无数据)</summary>
|
||
public static ApiResponse Succeed(string? message = null)
|
||
=> ApiResponse.Succeed(message);
|
||
|
||
/// <summary>失败返回</summary>
|
||
public static ApiResponse<T> Fail<T>(int code, string message, T? data = default)
|
||
=> ApiResponse<T>.Fail(code, message, data);
|
||
|
||
/// <summary>失败返回(无数据)</summary>
|
||
public static ApiResponse Failure(int code, string message)
|
||
=> ApiResponse.Failure(code, message);
|
||
|
||
/// <summary>分页返回</summary>
|
||
public static PagedResponse<T> Paged<T>(List<T> items, int total, int page, int pageSize)
|
||
=> PagedResponse<T>.From(items, total, page, pageSize);
|
||
}
|
||
}
|