Merge branch 'chore/comment-fix' into dev
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
public static class DatabaseConstants
|
||||
{
|
||||
/// <summary>
|
||||
/// 默认业务库(AppDatabase)。
|
||||
/// 默认业务库(AppDatabase).
|
||||
/// </summary>
|
||||
public const string AppDataSource = "AppDatabase";
|
||||
|
||||
|
||||
@@ -5,15 +5,43 @@ namespace TakeoutSaaS.Shared.Abstractions.Constants;
|
||||
/// </summary>
|
||||
public static class ErrorCodes
|
||||
{
|
||||
/// <summary>
|
||||
/// 请求参数错误。
|
||||
/// </summary>
|
||||
public const int BadRequest = 400;
|
||||
|
||||
/// <summary>
|
||||
/// 未授权访问。
|
||||
/// </summary>
|
||||
public const int Unauthorized = 401;
|
||||
|
||||
/// <summary>
|
||||
/// 权限不足。
|
||||
/// </summary>
|
||||
public const int Forbidden = 403;
|
||||
|
||||
/// <summary>
|
||||
/// 资源未找到。
|
||||
/// </summary>
|
||||
public const int NotFound = 404;
|
||||
|
||||
/// <summary>
|
||||
/// 资源冲突。
|
||||
/// </summary>
|
||||
public const int Conflict = 409;
|
||||
|
||||
/// <summary>
|
||||
/// 校验失败。
|
||||
/// </summary>
|
||||
public const int ValidationFailed = 422;
|
||||
|
||||
/// <summary>
|
||||
/// 服务器内部错误。
|
||||
/// </summary>
|
||||
public const int InternalServerError = 500;
|
||||
|
||||
// 业务自定义区间(10000+)
|
||||
/// <summary>
|
||||
/// 业务自定义错误(10000+)。
|
||||
/// </summary>
|
||||
public const int BusinessError = 10001;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ public interface IDapperExecutor
|
||||
/// <param name="role">连接角色(读/写)。</param>
|
||||
/// <param name="command">命令委托,提供已打开的连接和取消标记。</param>
|
||||
/// <param name="cancellationToken">取消标记。</param>
|
||||
/// <returns>异步执行任务。</returns>
|
||||
Task ExecuteAsync(
|
||||
string dataSourceName,
|
||||
DatabaseConnectionRole role,
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
using System.Threading;
|
||||
|
||||
namespace TakeoutSaaS.Shared.Abstractions.Diagnostics;
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace TakeoutSaaS.Shared.Abstractions.Exceptions;
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -8,24 +8,36 @@ public static class ApiResponse
|
||||
/// <summary>
|
||||
/// 仅返回成功消息(无数据)。
|
||||
/// </summary>
|
||||
/// <param name="message">提示信息。</param>
|
||||
/// <returns>封装后的成功响应。</returns>
|
||||
public static ApiResponse<object> Success(string? message = "操作成功")
|
||||
=> ApiResponse<object>.Ok(message: message);
|
||||
|
||||
/// <summary>
|
||||
/// 成功且携带数据。
|
||||
/// </summary>
|
||||
/// <param name="data">业务数据。</param>
|
||||
/// <param name="message">提示信息。</param>
|
||||
/// <returns>封装后的成功响应。</returns>
|
||||
public static ApiResponse<object> Ok(object? data, string? message = "操作成功")
|
||||
=> data is null ? ApiResponse<object>.Ok(message: message) : ApiResponse<object>.Ok(data, message);
|
||||
|
||||
/// <summary>
|
||||
/// 错误返回。
|
||||
/// </summary>
|
||||
/// <param name="code">错误码。</param>
|
||||
/// <param name="message">错误提示。</param>
|
||||
/// <returns>封装后的失败响应。</returns>
|
||||
public static ApiResponse<object> Failure(int code, string message)
|
||||
=> ApiResponse<object>.Error(code, message);
|
||||
|
||||
/// <summary>
|
||||
/// 错误返回(附带详情)。
|
||||
/// </summary>
|
||||
/// <param name="code">错误码。</param>
|
||||
/// <param name="message">错误提示。</param>
|
||||
/// <param name="errors">错误详情。</param>
|
||||
/// <returns>封装后的失败响应。</returns>
|
||||
public static ApiResponse<object> Error(int code, string message, object? errors = null)
|
||||
=> ApiResponse<object>.Error(code, message, errors);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace TakeoutSaaS.Shared.Abstractions.Results;
|
||||
/// <summary>
|
||||
/// 统一的 API 返回结果包装。
|
||||
/// </summary>
|
||||
/// <typeparam name="T">数据载荷类型</typeparam>
|
||||
/// <typeparam name="T">数据载荷类型。</typeparam>
|
||||
public sealed record ApiResponse<T>
|
||||
{
|
||||
/// <summary>
|
||||
@@ -47,36 +47,53 @@ public sealed record ApiResponse<T>
|
||||
/// <summary>
|
||||
/// 成功返回。
|
||||
/// </summary>
|
||||
/// <param name="data">业务数据。</param>
|
||||
/// <param name="message">提示信息。</param>
|
||||
/// <returns>封装后的成功响应。</returns>
|
||||
public static ApiResponse<T> Ok(T data, string? message = "操作成功")
|
||||
=> Create(true, 200, message, data);
|
||||
|
||||
/// <summary>
|
||||
/// 无数据的成功返回。
|
||||
/// </summary>
|
||||
/// <param name="message">提示信息。</param>
|
||||
/// <returns>封装后的成功响应。</returns>
|
||||
public static ApiResponse<T> Ok(string? message = "操作成功")
|
||||
=> Create(true, 200, message, default);
|
||||
|
||||
/// <summary>
|
||||
/// 兼容旧名称:成功结果。
|
||||
/// </summary>
|
||||
/// <param name="data">业务数据。</param>
|
||||
/// <param name="message">提示信息。</param>
|
||||
/// <returns>封装后的成功响应。</returns>
|
||||
public static ApiResponse<T> SuccessResult(T data, string? message = "操作成功")
|
||||
=> Ok(data, message);
|
||||
|
||||
/// <summary>
|
||||
/// 错误返回。
|
||||
/// </summary>
|
||||
/// <param name="code">错误码。</param>
|
||||
/// <param name="message">错误提示。</param>
|
||||
/// <param name="errors">错误详情。</param>
|
||||
/// <returns>封装后的失败响应。</returns>
|
||||
public static ApiResponse<T> Error(int code, string message, object? errors = null)
|
||||
=> Create(false, code, message, default, errors);
|
||||
|
||||
/// <summary>
|
||||
/// 兼容旧名称:失败结果。
|
||||
/// </summary>
|
||||
/// <param name="code">错误码。</param>
|
||||
/// <param name="message">错误提示。</param>
|
||||
/// <returns>封装后的失败响应。</returns>
|
||||
public static ApiResponse<T> Failure(int code, string message)
|
||||
=> Error(code, message);
|
||||
|
||||
/// <summary>
|
||||
/// 附加错误详情。
|
||||
/// </summary>
|
||||
/// <param name="errors">错误详情。</param>
|
||||
/// <returns>包含错误详情的新响应。</returns>
|
||||
public ApiResponse<T> WithErrors(object? errors)
|
||||
=> this with { Errors = errors };
|
||||
|
||||
@@ -92,6 +109,10 @@ public sealed record ApiResponse<T>
|
||||
Timestamp = DateTime.UtcNow
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// 解析当前 TraceId。
|
||||
/// </summary>
|
||||
/// <returns>当前有效的 TraceId。</returns>
|
||||
private static string ResolveTraceId()
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(TraceContext.TraceId))
|
||||
@@ -113,9 +134,19 @@ public sealed record ApiResponse<T>
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 作为 TraceId 缺失时的本地雪花 ID 备用生成器。
|
||||
/// </summary>
|
||||
internal sealed class IdFallbackGenerator
|
||||
{
|
||||
/// <summary>
|
||||
/// 延迟初始化的单例实例承载。
|
||||
/// </summary>
|
||||
private static readonly Lazy<IdFallbackGenerator> Lazy = new(() => new IdFallbackGenerator());
|
||||
|
||||
/// <summary>
|
||||
/// 获取备用雪花生成器单例。
|
||||
/// </summary>
|
||||
public static IdFallbackGenerator Instance => Lazy.Value;
|
||||
|
||||
private readonly object _sync = new();
|
||||
@@ -126,6 +157,10 @@ internal sealed class IdFallbackGenerator
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 生成雪花风格的本地备用 ID。
|
||||
/// </summary>
|
||||
/// <returns>本地生成的雪花 ID。</returns>
|
||||
public long NextId()
|
||||
{
|
||||
lock (_sync)
|
||||
@@ -149,6 +184,11 @@ internal sealed class IdFallbackGenerator
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 等待到下一个毫秒以避免序列冲突。
|
||||
/// </summary>
|
||||
/// <param name="lastTimestamp">上一毫秒的时间戳。</param>
|
||||
/// <returns>下一个时间戳(毫秒)。</returns>
|
||||
private static long WaitNextMillis(long lastTimestamp)
|
||||
{
|
||||
var timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace TakeoutSaaS.Shared.Abstractions.Results;
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -6,7 +6,8 @@ namespace TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||
public interface ITenantProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取当前租户 ID,未解析时返回 Guid.Empty。
|
||||
/// 获取当前租户 ID,未解析时返回 0。
|
||||
/// </summary>
|
||||
/// <returns>当前请求绑定的租户 ID,未解析时为 0。</returns>
|
||||
long GetCurrentTenantId();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System.Diagnostics;
|
||||
using System.Security.Cryptography;
|
||||
using System.Threading;
|
||||
using TakeoutSaaS.Shared.Abstractions.Ids;
|
||||
|
||||
namespace TakeoutSaaS.Shared.Kernel.Ids;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.ApiExplorer;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using TakeoutSaaS.Shared.Abstractions.Security;
|
||||
using TakeoutSaaS.Shared.Web.Filters;
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using TakeoutSaaS.Shared.Abstractions.Constants;
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Diagnostics;
|
||||
using TakeoutSaaS.Shared.Abstractions.Diagnostics;
|
||||
using TakeoutSaaS.Shared.Abstractions.Ids;
|
||||
|
||||
@@ -49,10 +46,10 @@ public sealed class CorrelationIdMiddleware(RequestDelegate next, ILogger<Correl
|
||||
});
|
||||
|
||||
using (logger.BeginScope(new Dictionary<string, object>
|
||||
{
|
||||
["TraceId"] = traceId,
|
||||
["SpanId"] = spanId
|
||||
}))
|
||||
{
|
||||
["TraceId"] = traceId,
|
||||
["SpanId"] = spanId
|
||||
}))
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using TakeoutSaaS.Shared.Abstractions.Constants;
|
||||
using TakeoutSaaS.Shared.Abstractions.Exceptions;
|
||||
using TakeoutSaaS.Shared.Abstractions.Results;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Diagnostics;
|
||||
using TakeoutSaaS.Shared.Abstractions.Diagnostics;
|
||||
|
||||
namespace TakeoutSaaS.Shared.Web.Middleware;
|
||||
@@ -11,7 +10,6 @@ namespace TakeoutSaaS.Shared.Web.Middleware;
|
||||
/// </summary>
|
||||
public sealed class RequestLoggingMiddleware(RequestDelegate next, ILogger<RequestLoggingMiddleware> logger)
|
||||
{
|
||||
|
||||
public async Task InvokeAsync(HttpContext context)
|
||||
{
|
||||
var stopwatch = Stopwatch.StartNew();
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using System;
|
||||
using System.Security.Claims;
|
||||
|
||||
namespace TakeoutSaaS.Shared.Web.Security;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using System.Security.Claims;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using System.Security.Claims;
|
||||
using TakeoutSaaS.Shared.Abstractions.Security;
|
||||
|
||||
namespace TakeoutSaaS.Shared.Web.Security;
|
||||
@@ -12,8 +12,6 @@ namespace TakeoutSaaS.Shared.Web.Security;
|
||||
/// </remarks>
|
||||
public sealed class HttpContextCurrentUserAccessor(IHttpContextAccessor httpContextAccessor) : ICurrentUserAccessor
|
||||
{
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public long UserId
|
||||
{
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Mvc.ApiExplorer;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Mvc.ApiExplorer;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.OpenApi;
|
||||
|
||||
Reference in New Issue
Block a user