feat: tenant门店管理首批接口落地
All checks were successful
Build and Deploy TenantApi / build-and-deploy (push) Successful in 30s

This commit is contained in:
2026-02-17 11:10:06 +08:00
parent 992930a821
commit 654b1ae3f7
31 changed files with 2731 additions and 14 deletions

View File

@@ -0,0 +1,112 @@
using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using TakeoutSaaS.Application.App.Stores.Commands;
using TakeoutSaaS.Application.App.Stores.Dto;
using TakeoutSaaS.Application.App.Stores.Queries;
using TakeoutSaaS.Shared.Abstractions.Results;
using TakeoutSaaS.Shared.Web.Api;
namespace TakeoutSaaS.TenantApi.Controllers;
/// <summary>
/// 租户端门店管理。
/// </summary>
[ApiVersion("1.0")]
[Authorize]
[Route("api/tenant/v{version:apiVersion}/store")]
public sealed class StoreController(IMediator mediator) : BaseApiController
{
/// <summary>
/// 查询门店列表。
/// </summary>
/// <param name="query">查询参数。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>分页列表。</returns>
[HttpGet("list")]
[ProducesResponseType(typeof(ApiResponse<StoreListResultDto>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ApiResponse<StoreListResultDto>), StatusCodes.Status401Unauthorized)]
public async Task<ApiResponse<StoreListResultDto>> List([FromQuery] SearchStoresQuery query, CancellationToken cancellationToken)
{
// 1. 查询门店分页
var result = await mediator.Send(query, cancellationToken);
// 2. 返回分页数据
return ApiResponse<StoreListResultDto>.Ok(result);
}
/// <summary>
/// 查询门店统计。
/// </summary>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>统计结果。</returns>
[HttpGet("stats")]
[ProducesResponseType(typeof(ApiResponse<StoreStatsDto>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ApiResponse<StoreStatsDto>), StatusCodes.Status401Unauthorized)]
public async Task<ApiResponse<StoreStatsDto>> Stats(CancellationToken cancellationToken)
{
// 1. 查询门店统计
var result = await mediator.Send(new GetStoreStatsQuery(), cancellationToken);
// 2. 返回统计结果
return ApiResponse<StoreStatsDto>.Ok(result);
}
/// <summary>
/// 创建门店。
/// </summary>
/// <param name="command">创建命令。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>创建结果。</returns>
[HttpPost("create")]
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status401Unauthorized)]
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status422UnprocessableEntity)]
public async Task<ApiResponse<object>> Create([FromBody] CreateStoreCommand command, CancellationToken cancellationToken)
{
// 1. 执行创建
await mediator.Send(command, cancellationToken);
// 2. 返回成功响应
return ApiResponse<object>.Ok(null);
}
/// <summary>
/// 更新门店。
/// </summary>
/// <param name="command">更新命令。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>更新结果。</returns>
[HttpPost("update")]
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status401Unauthorized)]
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status422UnprocessableEntity)]
public async Task<ApiResponse<object>> Update([FromBody] UpdateStoreCommand command, CancellationToken cancellationToken)
{
// 1. 执行更新
await mediator.Send(command, cancellationToken);
// 2. 返回成功响应
return ApiResponse<object>.Ok(null);
}
/// <summary>
/// 删除门店。
/// </summary>
/// <param name="command">删除命令。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>删除结果。</returns>
[HttpPost("delete")]
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status401Unauthorized)]
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status422UnprocessableEntity)]
public async Task<ApiResponse<object>> Delete([FromBody] DeleteStoreCommand command, CancellationToken cancellationToken)
{
// 1. 执行删除
await mediator.Send(command, cancellationToken);
// 2. 返回成功响应
return ApiResponse<object>.Ok(null);
}
}

View File

@@ -9,7 +9,11 @@ using OpenTelemetry.Metrics;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;
using Serilog;
using TakeoutSaaS.Application.App.Extensions;
using TakeoutSaaS.Infrastructure.App.Extensions;
using TakeoutSaaS.Infrastructure.Identity.Extensions;
using TakeoutSaaS.Module.Authorization.Extensions;
using TakeoutSaaS.Module.Tenancy.Extensions;
using TakeoutSaaS.Shared.Web.Extensions;
using TakeoutSaaS.Shared.Web.Security;
using TakeoutSaaS.Shared.Web.Swagger;
@@ -77,6 +81,10 @@ if (isDevelopment)
}
// 5. 注册鉴权授权与权限策略
builder.Services.AddAppApplication();
builder.Services.AddAppInfrastructure(builder.Configuration);
builder.Services.AddJwtAuthentication(builder.Configuration);
builder.Services.AddTenantResolution(builder.Configuration);
builder.Services.AddAuthorization();
builder.Services.AddPermissionAuthorization();
builder.Services.AddHealthChecks();
@@ -150,10 +158,14 @@ app.UseCors("TenantApiCors");
// 1. (空行后) 通用 Web Core 中间件异常、ProblemDetails、日志等
app.UseSharedWebCore();
// 2. (空行后) 执行授权
// 2. (空行后) 执行认证并解析租户
app.UseAuthentication();
app.UseTenantResolution();
// 3. (空行后) 执行授权
app.UseAuthorization();
// 3. (空行后) 开发环境启用 Swagger
// 4. (空行后) 开发环境启用 Swagger
if (app.Environment.IsDevelopment())
{
app.UseSharedSwagger();