feat(shared-web): add shared swagger and tracing utilities

This commit is contained in:
2025-11-22 21:20:49 +08:00
parent b9d4a06f61
commit b587e8c1e1
22 changed files with 1058 additions and 0 deletions

View File

@@ -0,0 +1,105 @@
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");
}
}