106 lines
2.8 KiB
C#
106 lines
2.8 KiB
C#
using System;
|
||
using System.Diagnostics;
|
||
using TakeoutSaaS.Shared.Abstractions.Diagnostics;
|
||
|
||
namespace TakeoutSaaS.Shared.Abstractions.Results;
|
||
|
||
/// <summary>
|
||
/// 统一的 API 返回结果包装。
|
||
/// </summary>
|
||
/// <typeparam name="T">数据载荷类型</typeparam>
|
||
public sealed record class ApiResponse<T>
|
||
{
|
||
/// <summary>
|
||
/// 是否成功。
|
||
/// </summary>
|
||
public bool Success { get; init; }
|
||
|
||
/// <summary>
|
||
/// 状态/错误码(默认 200)。
|
||
/// </summary>
|
||
public int Code { get; init; } = 200;
|
||
|
||
/// <summary>
|
||
/// 提示信息。
|
||
/// </summary>
|
||
public string? Message { get; init; }
|
||
|
||
/// <summary>
|
||
/// 业务数据。
|
||
/// </summary>
|
||
public T? Data { get; init; }
|
||
|
||
/// <summary>
|
||
/// 错误详情(如字段验证错误)。
|
||
/// </summary>
|
||
public object? Errors { get; init; }
|
||
|
||
/// <summary>
|
||
/// TraceId,便于链路追踪。
|
||
/// </summary>
|
||
public string TraceId { get; init; } = string.Empty;
|
||
|
||
/// <summary>
|
||
/// 时间戳(UTC)。
|
||
/// </summary>
|
||
public DateTime Timestamp { get; init; } = DateTime.UtcNow;
|
||
|
||
/// <summary>
|
||
/// 成功返回。
|
||
/// </summary>
|
||
public static ApiResponse<T> Ok(T data, string? message = "操作成功")
|
||
=> Create(true, 200, message, data);
|
||
|
||
/// <summary>
|
||
/// 无数据的成功返回。
|
||
/// </summary>
|
||
public static ApiResponse<T> Ok(string? message = "操作成功")
|
||
=> Create(true, 200, message, default);
|
||
|
||
/// <summary>
|
||
/// 兼容旧名称:成功结果。
|
||
/// </summary>
|
||
public static ApiResponse<T> SuccessResult(T data, string? message = "操作成功")
|
||
=> Ok(data, message);
|
||
|
||
/// <summary>
|
||
/// 错误返回。
|
||
/// </summary>
|
||
public static ApiResponse<T> Error(int code, string message, object? errors = null)
|
||
=> Create(false, code, message, default, errors);
|
||
|
||
/// <summary>
|
||
/// 兼容旧名称:失败结果。
|
||
/// </summary>
|
||
public static ApiResponse<T> Failure(int code, string message)
|
||
=> Error(code, message);
|
||
|
||
/// <summary>
|
||
/// 附加错误详情。
|
||
/// </summary>
|
||
public ApiResponse<T> WithErrors(object? errors)
|
||
=> this with { Errors = errors };
|
||
|
||
private static ApiResponse<T> Create(bool success, int code, string? message, T? data, object? errors = null)
|
||
=> new()
|
||
{
|
||
Success = success,
|
||
Code = code,
|
||
Message = message,
|
||
Data = data,
|
||
Errors = errors,
|
||
TraceId = ResolveTraceId(),
|
||
Timestamp = DateTime.UtcNow
|
||
};
|
||
|
||
private static string ResolveTraceId()
|
||
{
|
||
if (!string.IsNullOrWhiteSpace(TraceContext.TraceId))
|
||
{
|
||
return TraceContext.TraceId!;
|
||
}
|
||
|
||
return Activity.Current?.Id ?? Guid.NewGuid().ToString("N");
|
||
}
|
||
}
|