chore: add documentation comments and stylecop rules
This commit is contained in:
@@ -13,21 +13,16 @@ using TakeoutSaaS.Shared.Web.Api;
|
||||
using TakeoutSaaS.Shared.Web.Security;
|
||||
|
||||
namespace TakeoutSaaS.AdminApi.Controllers;
|
||||
|
||||
/// <summary>
|
||||
/// 管理后台认证接口
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
///
|
||||
/// </remarks>
|
||||
/// <param name="authService"></param>
|
||||
/// <remarks>提供登录、刷新 Token 以及用户权限查询能力。</remarks>
|
||||
/// <param name="authService">认证服务</param>
|
||||
[ApiVersion("1.0")]
|
||||
[Authorize]
|
||||
[Route("api/admin/v{version:apiVersion}/auth")]
|
||||
public sealed class AuthController(IAdminAuthService authService) : BaseApiController
|
||||
{
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 登录获取 Token
|
||||
/// </summary>
|
||||
@@ -84,12 +79,14 @@ public sealed class AuthController(IAdminAuthService authService) : BaseApiContr
|
||||
[ProducesResponseType(typeof(ApiResponse<CurrentUserProfile>), StatusCodes.Status401Unauthorized)]
|
||||
public async Task<ApiResponse<CurrentUserProfile>> GetProfile(CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 从 JWT 中获取当前用户标识
|
||||
var userId = User.GetUserId();
|
||||
if (userId == 0)
|
||||
{
|
||||
return ApiResponse<CurrentUserProfile>.Error(ErrorCodes.Unauthorized, "Token 缺少有效的用户标识");
|
||||
}
|
||||
|
||||
// 2. 读取用户档案并返回
|
||||
var profile = await authService.GetProfileAsync(userId, cancellationToken);
|
||||
return ApiResponse<CurrentUserProfile>.Ok(profile);
|
||||
}
|
||||
|
||||
@@ -16,16 +16,11 @@ namespace TakeoutSaaS.AdminApi.Controllers;
|
||||
/// <summary>
|
||||
/// 配送单管理。
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 初始化控制器。
|
||||
/// </remarks>
|
||||
[ApiVersion("1.0")]
|
||||
[Authorize]
|
||||
[Route("api/admin/v{version:apiVersion}/deliveries")]
|
||||
public sealed class DeliveriesController(IMediator mediator) : BaseApiController
|
||||
{
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 创建配送单。
|
||||
/// </summary>
|
||||
@@ -34,7 +29,10 @@ public sealed class DeliveriesController(IMediator mediator) : BaseApiController
|
||||
[ProducesResponseType(typeof(ApiResponse<DeliveryOrderDto>), StatusCodes.Status200OK)]
|
||||
public async Task<ApiResponse<DeliveryOrderDto>> Create([FromBody] CreateDeliveryOrderCommand command, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 创建配送单
|
||||
var result = await mediator.Send(command, cancellationToken);
|
||||
|
||||
// 2. 返回创建结果
|
||||
return ApiResponse<DeliveryOrderDto>.Ok(result);
|
||||
}
|
||||
|
||||
@@ -53,6 +51,7 @@ public sealed class DeliveriesController(IMediator mediator) : BaseApiController
|
||||
[FromQuery] bool sortDesc = true,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
// 1. 组装查询参数
|
||||
var result = await mediator.Send(new SearchDeliveryOrdersQuery
|
||||
{
|
||||
OrderId = orderId,
|
||||
@@ -63,6 +62,7 @@ public sealed class DeliveriesController(IMediator mediator) : BaseApiController
|
||||
SortDescending = sortDesc
|
||||
}, cancellationToken);
|
||||
|
||||
// 2. 返回分页结果
|
||||
return ApiResponse<PagedResult<DeliveryOrderDto>>.Ok(result);
|
||||
}
|
||||
|
||||
@@ -75,7 +75,10 @@ public sealed class DeliveriesController(IMediator mediator) : BaseApiController
|
||||
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status404NotFound)]
|
||||
public async Task<ApiResponse<DeliveryOrderDto>> Detail(long deliveryOrderId, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 查询配送单详情
|
||||
var result = await mediator.Send(new GetDeliveryOrderByIdQuery { DeliveryOrderId = deliveryOrderId }, cancellationToken);
|
||||
|
||||
// 2. 返回详情或 404
|
||||
return result == null
|
||||
? ApiResponse<DeliveryOrderDto>.Error(ErrorCodes.NotFound, "配送单不存在")
|
||||
: ApiResponse<DeliveryOrderDto>.Ok(result);
|
||||
@@ -90,11 +93,16 @@ public sealed class DeliveriesController(IMediator mediator) : BaseApiController
|
||||
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status404NotFound)]
|
||||
public async Task<ApiResponse<DeliveryOrderDto>> Update(long deliveryOrderId, [FromBody] UpdateDeliveryOrderCommand command, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 确保命令携带配送单标识
|
||||
if (command.DeliveryOrderId == 0)
|
||||
{
|
||||
command = command with { DeliveryOrderId = deliveryOrderId };
|
||||
}
|
||||
|
||||
// 2. 执行更新
|
||||
var result = await mediator.Send(command, cancellationToken);
|
||||
|
||||
// 3. 返回更新结果或 404
|
||||
return result == null
|
||||
? ApiResponse<DeliveryOrderDto>.Error(ErrorCodes.NotFound, "配送单不存在")
|
||||
: ApiResponse<DeliveryOrderDto>.Ok(result);
|
||||
@@ -109,7 +117,10 @@ public sealed class DeliveriesController(IMediator mediator) : BaseApiController
|
||||
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status404NotFound)]
|
||||
public async Task<ApiResponse<object>> Delete(long deliveryOrderId, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 执行删除
|
||||
var success = await mediator.Send(new DeleteDeliveryOrderCommand { DeliveryOrderId = deliveryOrderId }, cancellationToken);
|
||||
|
||||
// 2. 返回结果或 404
|
||||
return success
|
||||
? ApiResponse<object>.Ok(null)
|
||||
: ApiResponse<object>.Error(ErrorCodes.NotFound, "配送单不存在");
|
||||
|
||||
@@ -12,17 +12,12 @@ namespace TakeoutSaaS.AdminApi.Controllers;
|
||||
/// <summary>
|
||||
/// 参数字典管理。
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 初始化字典控制器。
|
||||
/// </remarks>
|
||||
/// <param name="dictionaryAppService">字典服务</param>
|
||||
[ApiVersion("1.0")]
|
||||
[Authorize]
|
||||
[Route("api/admin/v{version:apiVersion}/dictionaries")]
|
||||
public sealed class DictionaryController(IDictionaryAppService dictionaryAppService) : BaseApiController
|
||||
{
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 查询字典分组。
|
||||
/// </summary>
|
||||
@@ -31,7 +26,10 @@ public sealed class DictionaryController(IDictionaryAppService dictionaryAppServ
|
||||
[ProducesResponseType(typeof(ApiResponse<IReadOnlyList<DictionaryGroupDto>>), StatusCodes.Status200OK)]
|
||||
public async Task<ApiResponse<IReadOnlyList<DictionaryGroupDto>>> GetGroups([FromQuery] DictionaryGroupQuery query, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 查询字典分组
|
||||
var groups = await dictionaryAppService.SearchGroupsAsync(query, cancellationToken);
|
||||
|
||||
// 2. 返回分组列表
|
||||
return ApiResponse<IReadOnlyList<DictionaryGroupDto>>.Ok(groups);
|
||||
}
|
||||
|
||||
@@ -43,7 +41,10 @@ public sealed class DictionaryController(IDictionaryAppService dictionaryAppServ
|
||||
[ProducesResponseType(typeof(ApiResponse<DictionaryGroupDto>), StatusCodes.Status200OK)]
|
||||
public async Task<ApiResponse<DictionaryGroupDto>> CreateGroup([FromBody] CreateDictionaryGroupRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 创建字典分组
|
||||
var group = await dictionaryAppService.CreateGroupAsync(request, cancellationToken);
|
||||
|
||||
// 2. 返回创建结果
|
||||
return ApiResponse<DictionaryGroupDto>.Ok(group);
|
||||
}
|
||||
|
||||
@@ -55,7 +56,10 @@ public sealed class DictionaryController(IDictionaryAppService dictionaryAppServ
|
||||
[ProducesResponseType(typeof(ApiResponse<DictionaryGroupDto>), StatusCodes.Status200OK)]
|
||||
public async Task<ApiResponse<DictionaryGroupDto>> UpdateGroup(long groupId, [FromBody] UpdateDictionaryGroupRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 更新字典分组
|
||||
var group = await dictionaryAppService.UpdateGroupAsync(groupId, request, cancellationToken);
|
||||
|
||||
// 2. 返回更新结果
|
||||
return ApiResponse<DictionaryGroupDto>.Ok(group);
|
||||
}
|
||||
|
||||
@@ -67,7 +71,10 @@ public sealed class DictionaryController(IDictionaryAppService dictionaryAppServ
|
||||
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status200OK)]
|
||||
public async Task<ApiResponse<object>> DeleteGroup(long groupId, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 删除字典分组
|
||||
await dictionaryAppService.DeleteGroupAsync(groupId, cancellationToken);
|
||||
|
||||
// 2. 返回成功响应
|
||||
return ApiResponse.Success();
|
||||
}
|
||||
|
||||
@@ -79,7 +86,10 @@ public sealed class DictionaryController(IDictionaryAppService dictionaryAppServ
|
||||
[ProducesResponseType(typeof(ApiResponse<DictionaryItemDto>), StatusCodes.Status200OK)]
|
||||
public async Task<ApiResponse<DictionaryItemDto>> CreateItem(long groupId, [FromBody] CreateDictionaryItemRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 绑定分组标识
|
||||
request.GroupId = groupId;
|
||||
|
||||
// 2. 创建字典项
|
||||
var item = await dictionaryAppService.CreateItemAsync(request, cancellationToken);
|
||||
return ApiResponse<DictionaryItemDto>.Ok(item);
|
||||
}
|
||||
@@ -92,7 +102,10 @@ public sealed class DictionaryController(IDictionaryAppService dictionaryAppServ
|
||||
[ProducesResponseType(typeof(ApiResponse<DictionaryItemDto>), StatusCodes.Status200OK)]
|
||||
public async Task<ApiResponse<DictionaryItemDto>> UpdateItem(long itemId, [FromBody] UpdateDictionaryItemRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 更新字典项
|
||||
var item = await dictionaryAppService.UpdateItemAsync(itemId, request, cancellationToken);
|
||||
|
||||
// 2. 返回更新结果
|
||||
return ApiResponse<DictionaryItemDto>.Ok(item);
|
||||
}
|
||||
|
||||
@@ -104,7 +117,10 @@ public sealed class DictionaryController(IDictionaryAppService dictionaryAppServ
|
||||
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status200OK)]
|
||||
public async Task<ApiResponse<object>> DeleteItem(long itemId, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 删除字典项
|
||||
await dictionaryAppService.DeleteItemAsync(itemId, cancellationToken);
|
||||
|
||||
// 2. 返回成功响应
|
||||
return ApiResponse.Success();
|
||||
}
|
||||
|
||||
@@ -115,7 +131,10 @@ public sealed class DictionaryController(IDictionaryAppService dictionaryAppServ
|
||||
[ProducesResponseType(typeof(ApiResponse<IReadOnlyDictionary<string, IReadOnlyList<DictionaryItemDto>>>), StatusCodes.Status200OK)]
|
||||
public async Task<ApiResponse<IReadOnlyDictionary<string, IReadOnlyList<DictionaryItemDto>>>> BatchGet([FromBody] DictionaryBatchQueryRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 批量读取并命中缓存
|
||||
var dictionaries = await dictionaryAppService.GetCachedItemsAsync(request, cancellationToken);
|
||||
|
||||
// 2. 返回批量结果
|
||||
return ApiResponse<IReadOnlyDictionary<string, IReadOnlyList<DictionaryItemDto>>>.Ok(dictionaries);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,8 +19,6 @@ namespace TakeoutSaaS.AdminApi.Controllers;
|
||||
[Route("api/admin/v{version:apiVersion}/files")]
|
||||
public sealed class FilesController(IFileStorageService fileStorageService) : BaseApiController
|
||||
{
|
||||
private readonly IFileStorageService _fileStorageService = fileStorageService;
|
||||
|
||||
/// <summary>
|
||||
/// 上传图片或文件。
|
||||
/// </summary>
|
||||
@@ -30,23 +28,28 @@ public sealed class FilesController(IFileStorageService fileStorageService) : Ba
|
||||
[ProducesResponseType(typeof(ApiResponse<FileUploadResponse>), StatusCodes.Status400BadRequest)]
|
||||
public async Task<ApiResponse<FileUploadResponse>> Upload([FromForm] IFormFile? file, [FromForm] string? type, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 校验文件有效性
|
||||
if (file == null || file.Length == 0)
|
||||
{
|
||||
return ApiResponse<FileUploadResponse>.Error(ErrorCodes.BadRequest, "文件不能为空");
|
||||
}
|
||||
|
||||
// 2. 解析上传类型
|
||||
if (!UploadFileTypeParser.TryParse(type, out var uploadType))
|
||||
{
|
||||
return ApiResponse<FileUploadResponse>.Error(ErrorCodes.BadRequest, "上传类型不合法");
|
||||
}
|
||||
|
||||
// 3. 提取请求来源
|
||||
var origin = Request.Headers["Origin"].FirstOrDefault() ?? Request.Headers["Referer"].FirstOrDefault();
|
||||
await using var stream = file.OpenReadStream();
|
||||
|
||||
var result = await _fileStorageService.UploadAsync(
|
||||
// 4. 调用存储服务执行上传
|
||||
var result = await fileStorageService.UploadAsync(
|
||||
new UploadFileRequest(uploadType, stream, file.FileName, file.ContentType ?? string.Empty, file.Length, origin),
|
||||
cancellationToken);
|
||||
|
||||
// 5. 返回上传结果
|
||||
return ApiResponse<FileUploadResponse>.Ok(result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,10 @@ public class HealthController : BaseApiController
|
||||
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status200OK)]
|
||||
public ApiResponse<object> Get()
|
||||
{
|
||||
// 1. 构造健康状态
|
||||
var payload = new { status = "OK", service = "AdminApi", time = DateTime.UtcNow };
|
||||
|
||||
// 2. 返回健康响应
|
||||
return ApiResponse<object>.Ok(payload);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,10 @@ public sealed class MerchantCategoriesController(IMediator mediator) : BaseApiCo
|
||||
[ProducesResponseType(typeof(ApiResponse<IReadOnlyList<MerchantCategoryDto>>), StatusCodes.Status200OK)]
|
||||
public async Task<ApiResponse<IReadOnlyList<MerchantCategoryDto>>> List(CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 查询所有类目
|
||||
var result = await mediator.Send(new ListMerchantCategoriesQuery(), cancellationToken);
|
||||
|
||||
// 2. 返回类目列表
|
||||
return ApiResponse<IReadOnlyList<MerchantCategoryDto>>.Ok(result);
|
||||
}
|
||||
|
||||
@@ -41,7 +44,10 @@ public sealed class MerchantCategoriesController(IMediator mediator) : BaseApiCo
|
||||
[ProducesResponseType(typeof(ApiResponse<MerchantCategoryDto>), StatusCodes.Status200OK)]
|
||||
public async Task<ApiResponse<MerchantCategoryDto>> Create([FromBody] CreateMerchantCategoryCommand command, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 创建类目
|
||||
var result = await mediator.Send(command, cancellationToken);
|
||||
|
||||
// 2. 返回创建结果
|
||||
return ApiResponse<MerchantCategoryDto>.Ok(result);
|
||||
}
|
||||
|
||||
@@ -54,7 +60,10 @@ public sealed class MerchantCategoriesController(IMediator mediator) : BaseApiCo
|
||||
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status404NotFound)]
|
||||
public async Task<ApiResponse<object>> Delete(long categoryId, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 执行删除
|
||||
var success = await mediator.Send(new DeleteMerchantCategoryCommand(categoryId), cancellationToken);
|
||||
|
||||
// 2. 返回删除结果或 404
|
||||
return success
|
||||
? ApiResponse<object>.Ok(null)
|
||||
: ApiResponse<object>.Error(ErrorCodes.NotFound, "类目不存在");
|
||||
@@ -68,7 +77,10 @@ public sealed class MerchantCategoriesController(IMediator mediator) : BaseApiCo
|
||||
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status200OK)]
|
||||
public async Task<ApiResponse<object>> Reorder([FromBody] ReorderMerchantCategoriesCommand command, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 执行排序调整
|
||||
await mediator.Send(command, cancellationToken);
|
||||
|
||||
// 2. 返回成功结果
|
||||
return ApiResponse<object>.Ok(null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,16 +16,11 @@ namespace TakeoutSaaS.AdminApi.Controllers;
|
||||
/// <summary>
|
||||
/// 商户管理。
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 初始化控制器。
|
||||
/// </remarks>
|
||||
[ApiVersion("1.0")]
|
||||
[Authorize]
|
||||
[Route("api/admin/v{version:apiVersion}/merchants")]
|
||||
public sealed class MerchantsController(IMediator mediator) : BaseApiController
|
||||
{
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 创建商户。
|
||||
/// </summary>
|
||||
@@ -34,7 +29,10 @@ public sealed class MerchantsController(IMediator mediator) : BaseApiController
|
||||
[ProducesResponseType(typeof(ApiResponse<MerchantDto>), StatusCodes.Status200OK)]
|
||||
public async Task<ApiResponse<MerchantDto>> Create([FromBody] CreateMerchantCommand command, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 创建商户
|
||||
var result = await mediator.Send(command, cancellationToken);
|
||||
|
||||
// 2. 返回创建结果
|
||||
return ApiResponse<MerchantDto>.Ok(result);
|
||||
}
|
||||
|
||||
@@ -52,6 +50,7 @@ public sealed class MerchantsController(IMediator mediator) : BaseApiController
|
||||
[FromQuery] bool sortDesc = true,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
// 1. 组装查询参数并执行查询
|
||||
var result = await mediator.Send(new SearchMerchantsQuery
|
||||
{
|
||||
Status = status,
|
||||
@@ -60,6 +59,8 @@ public sealed class MerchantsController(IMediator mediator) : BaseApiController
|
||||
SortBy = sortBy,
|
||||
SortDescending = sortDesc
|
||||
}, cancellationToken);
|
||||
|
||||
// 2. 返回分页结果
|
||||
return ApiResponse<PagedResult<MerchantDto>>.Ok(result);
|
||||
}
|
||||
|
||||
@@ -72,12 +73,16 @@ public sealed class MerchantsController(IMediator mediator) : BaseApiController
|
||||
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status404NotFound)]
|
||||
public async Task<ApiResponse<MerchantDto>> Update(long merchantId, [FromBody] UpdateMerchantCommand command, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 绑定商户标识
|
||||
if (command.MerchantId == 0)
|
||||
{
|
||||
command = command with { MerchantId = merchantId };
|
||||
}
|
||||
|
||||
// 2. 执行更新
|
||||
var result = await mediator.Send(command, cancellationToken);
|
||||
|
||||
// 3. 返回更新结果或 404
|
||||
return result == null
|
||||
? ApiResponse<MerchantDto>.Error(ErrorCodes.NotFound, "商户不存在")
|
||||
: ApiResponse<MerchantDto>.Ok(result);
|
||||
@@ -92,7 +97,10 @@ public sealed class MerchantsController(IMediator mediator) : BaseApiController
|
||||
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status404NotFound)]
|
||||
public async Task<ApiResponse<object>> Delete(long merchantId, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 执行删除
|
||||
var success = await mediator.Send(new DeleteMerchantCommand { MerchantId = merchantId }, cancellationToken);
|
||||
|
||||
// 2. 返回删除结果或 404
|
||||
return success
|
||||
? ApiResponse<object>.Ok(null)
|
||||
: ApiResponse<object>.Error(ErrorCodes.NotFound, "商户不存在");
|
||||
@@ -107,7 +115,10 @@ public sealed class MerchantsController(IMediator mediator) : BaseApiController
|
||||
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status404NotFound)]
|
||||
public async Task<ApiResponse<MerchantDto>> Detail(long merchantId, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 查询商户概览
|
||||
var result = await mediator.Send(new GetMerchantByIdQuery { MerchantId = merchantId }, cancellationToken);
|
||||
|
||||
// 2. 返回结果或 404
|
||||
return result == null
|
||||
? ApiResponse<MerchantDto>.Error(ErrorCodes.NotFound, "商户不存在")
|
||||
: ApiResponse<MerchantDto>.Ok(result);
|
||||
@@ -121,7 +132,10 @@ public sealed class MerchantsController(IMediator mediator) : BaseApiController
|
||||
[ProducesResponseType(typeof(ApiResponse<MerchantDetailDto>), StatusCodes.Status200OK)]
|
||||
public async Task<ApiResponse<MerchantDetailDto>> FullDetail(long merchantId, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 查询商户详细资料
|
||||
var result = await mediator.Send(new GetMerchantDetailQuery(merchantId), cancellationToken);
|
||||
|
||||
// 2. 返回详情
|
||||
return ApiResponse<MerchantDetailDto>.Ok(result);
|
||||
}
|
||||
|
||||
@@ -136,7 +150,10 @@ public sealed class MerchantsController(IMediator mediator) : BaseApiController
|
||||
[FromBody] AddMerchantDocumentCommand body,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 绑定商户标识
|
||||
var command = body with { MerchantId = merchantId };
|
||||
|
||||
// 2. 创建证照记录
|
||||
var result = await mediator.Send(command, cancellationToken);
|
||||
return ApiResponse<MerchantDocumentDto>.Ok(result);
|
||||
}
|
||||
@@ -149,7 +166,10 @@ public sealed class MerchantsController(IMediator mediator) : BaseApiController
|
||||
[ProducesResponseType(typeof(ApiResponse<IReadOnlyList<MerchantDocumentDto>>), StatusCodes.Status200OK)]
|
||||
public async Task<ApiResponse<IReadOnlyList<MerchantDocumentDto>>> Documents(long merchantId, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 查询证照列表
|
||||
var result = await mediator.Send(new GetMerchantDocumentsQuery(merchantId), cancellationToken);
|
||||
|
||||
// 2. 返回证照集合
|
||||
return ApiResponse<IReadOnlyList<MerchantDocumentDto>>.Ok(result);
|
||||
}
|
||||
|
||||
@@ -165,7 +185,10 @@ public sealed class MerchantsController(IMediator mediator) : BaseApiController
|
||||
[FromBody] ReviewMerchantDocumentCommand body,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 绑定商户与证照标识
|
||||
var command = body with { MerchantId = merchantId, DocumentId = documentId };
|
||||
|
||||
// 2. 执行审核
|
||||
var result = await mediator.Send(command, cancellationToken);
|
||||
return ApiResponse<MerchantDocumentDto>.Ok(result);
|
||||
}
|
||||
@@ -181,7 +204,10 @@ public sealed class MerchantsController(IMediator mediator) : BaseApiController
|
||||
[FromBody] CreateMerchantContractCommand body,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 绑定商户标识
|
||||
var command = body with { MerchantId = merchantId };
|
||||
|
||||
// 2. 创建合同
|
||||
var result = await mediator.Send(command, cancellationToken);
|
||||
return ApiResponse<MerchantContractDto>.Ok(result);
|
||||
}
|
||||
@@ -194,7 +220,10 @@ public sealed class MerchantsController(IMediator mediator) : BaseApiController
|
||||
[ProducesResponseType(typeof(ApiResponse<IReadOnlyList<MerchantContractDto>>), StatusCodes.Status200OK)]
|
||||
public async Task<ApiResponse<IReadOnlyList<MerchantContractDto>>> Contracts(long merchantId, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 查询合同列表
|
||||
var result = await mediator.Send(new GetMerchantContractsQuery(merchantId), cancellationToken);
|
||||
|
||||
// 2. 返回合同集合
|
||||
return ApiResponse<IReadOnlyList<MerchantContractDto>>.Ok(result);
|
||||
}
|
||||
|
||||
@@ -210,7 +239,10 @@ public sealed class MerchantsController(IMediator mediator) : BaseApiController
|
||||
[FromBody] UpdateMerchantContractStatusCommand body,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 绑定商户与合同标识
|
||||
var command = body with { MerchantId = merchantId, ContractId = contractId };
|
||||
|
||||
// 2. 更新合同状态
|
||||
var result = await mediator.Send(command, cancellationToken);
|
||||
return ApiResponse<MerchantContractDto>.Ok(result);
|
||||
}
|
||||
@@ -223,7 +255,10 @@ public sealed class MerchantsController(IMediator mediator) : BaseApiController
|
||||
[ProducesResponseType(typeof(ApiResponse<MerchantDto>), StatusCodes.Status200OK)]
|
||||
public async Task<ApiResponse<MerchantDto>> Review(long merchantId, [FromBody] ReviewMerchantCommand body, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 绑定商户标识
|
||||
var command = body with { MerchantId = merchantId };
|
||||
|
||||
// 2. 执行审核
|
||||
var result = await mediator.Send(command, cancellationToken);
|
||||
return ApiResponse<MerchantDto>.Ok(result);
|
||||
}
|
||||
@@ -240,7 +275,10 @@ public sealed class MerchantsController(IMediator mediator) : BaseApiController
|
||||
[FromQuery] int pageSize = 20,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
// 1. 查询审核日志
|
||||
var result = await mediator.Send(new GetMerchantAuditLogsQuery(merchantId, page, pageSize), cancellationToken);
|
||||
|
||||
// 2. 返回日志分页
|
||||
return ApiResponse<PagedResult<MerchantAuditLogDto>>.Ok(result);
|
||||
}
|
||||
|
||||
@@ -252,7 +290,10 @@ public sealed class MerchantsController(IMediator mediator) : BaseApiController
|
||||
[ProducesResponseType(typeof(ApiResponse<IReadOnlyList<string>>), StatusCodes.Status200OK)]
|
||||
public async Task<ApiResponse<IReadOnlyList<string>>> Categories(CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 查询可选类目
|
||||
var result = await mediator.Send(new GetMerchantCategoriesQuery(), cancellationToken);
|
||||
|
||||
// 2. 返回类目列表
|
||||
return ApiResponse<IReadOnlyList<string>>.Ok(result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,16 +17,11 @@ namespace TakeoutSaaS.AdminApi.Controllers;
|
||||
/// <summary>
|
||||
/// 订单管理。
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 初始化控制器。
|
||||
/// </remarks>
|
||||
[ApiVersion("1.0")]
|
||||
[Authorize]
|
||||
[Route("api/admin/v{version:apiVersion}/orders")]
|
||||
public sealed class OrdersController(IMediator mediator) : BaseApiController
|
||||
{
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 创建订单。
|
||||
/// </summary>
|
||||
@@ -35,7 +30,10 @@ public sealed class OrdersController(IMediator mediator) : BaseApiController
|
||||
[ProducesResponseType(typeof(ApiResponse<OrderDto>), StatusCodes.Status200OK)]
|
||||
public async Task<ApiResponse<OrderDto>> Create([FromBody] CreateOrderCommand command, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 创建订单
|
||||
var result = await mediator.Send(command, cancellationToken);
|
||||
|
||||
// 2. 返回创建结果
|
||||
return ApiResponse<OrderDto>.Ok(result);
|
||||
}
|
||||
|
||||
@@ -56,6 +54,7 @@ public sealed class OrdersController(IMediator mediator) : BaseApiController
|
||||
[FromQuery] bool sortDesc = true,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
// 1. 组装查询参数并执行查询
|
||||
var result = await mediator.Send(new SearchOrdersQuery
|
||||
{
|
||||
StoreId = storeId,
|
||||
@@ -68,6 +67,7 @@ public sealed class OrdersController(IMediator mediator) : BaseApiController
|
||||
SortDescending = sortDesc
|
||||
}, cancellationToken);
|
||||
|
||||
// 2. 返回分页结果
|
||||
return ApiResponse<PagedResult<OrderDto>>.Ok(result);
|
||||
}
|
||||
|
||||
@@ -80,7 +80,10 @@ public sealed class OrdersController(IMediator mediator) : BaseApiController
|
||||
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status404NotFound)]
|
||||
public async Task<ApiResponse<OrderDto>> Detail(long orderId, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 查询订单详情
|
||||
var result = await mediator.Send(new GetOrderByIdQuery { OrderId = orderId }, cancellationToken);
|
||||
|
||||
// 2. 返回详情或 404
|
||||
return result == null
|
||||
? ApiResponse<OrderDto>.Error(ErrorCodes.NotFound, "订单不存在")
|
||||
: ApiResponse<OrderDto>.Ok(result);
|
||||
@@ -95,11 +98,16 @@ public sealed class OrdersController(IMediator mediator) : BaseApiController
|
||||
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status404NotFound)]
|
||||
public async Task<ApiResponse<OrderDto>> Update(long orderId, [FromBody] UpdateOrderCommand command, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 确保命令包含订单标识
|
||||
if (command.OrderId == 0)
|
||||
{
|
||||
command = command with { OrderId = orderId };
|
||||
}
|
||||
|
||||
// 2. 执行更新
|
||||
var result = await mediator.Send(command, cancellationToken);
|
||||
|
||||
// 3. 返回更新结果或 404
|
||||
return result == null
|
||||
? ApiResponse<OrderDto>.Error(ErrorCodes.NotFound, "订单不存在")
|
||||
: ApiResponse<OrderDto>.Ok(result);
|
||||
@@ -114,7 +122,10 @@ public sealed class OrdersController(IMediator mediator) : BaseApiController
|
||||
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status404NotFound)]
|
||||
public async Task<ApiResponse<object>> Delete(long orderId, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 执行删除
|
||||
var success = await mediator.Send(new DeleteOrderCommand { OrderId = orderId }, cancellationToken);
|
||||
|
||||
// 2. 返回结果或 404
|
||||
return success
|
||||
? ApiResponse<object>.Ok(null)
|
||||
: ApiResponse<object>.Error(ErrorCodes.NotFound, "订单不存在");
|
||||
|
||||
@@ -16,16 +16,11 @@ namespace TakeoutSaaS.AdminApi.Controllers;
|
||||
/// <summary>
|
||||
/// 支付记录管理。
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 初始化控制器。
|
||||
/// </remarks>
|
||||
[ApiVersion("1.0")]
|
||||
[Authorize]
|
||||
[Route("api/admin/v{version:apiVersion}/payments")]
|
||||
public sealed class PaymentsController(IMediator mediator) : BaseApiController
|
||||
{
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 创建支付记录。
|
||||
/// </summary>
|
||||
@@ -34,7 +29,10 @@ public sealed class PaymentsController(IMediator mediator) : BaseApiController
|
||||
[ProducesResponseType(typeof(ApiResponse<PaymentDto>), StatusCodes.Status200OK)]
|
||||
public async Task<ApiResponse<PaymentDto>> Create([FromBody] CreatePaymentCommand command, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 创建支付记录
|
||||
var result = await mediator.Send(command, cancellationToken);
|
||||
|
||||
// 2. 返回创建结果
|
||||
return ApiResponse<PaymentDto>.Ok(result);
|
||||
}
|
||||
|
||||
@@ -53,6 +51,7 @@ public sealed class PaymentsController(IMediator mediator) : BaseApiController
|
||||
[FromQuery] bool sortDesc = true,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
// 1. 组装查询参数并执行查询
|
||||
var result = await mediator.Send(new SearchPaymentsQuery
|
||||
{
|
||||
OrderId = orderId,
|
||||
@@ -63,6 +62,7 @@ public sealed class PaymentsController(IMediator mediator) : BaseApiController
|
||||
SortDescending = sortDesc
|
||||
}, cancellationToken);
|
||||
|
||||
// 2. 返回分页结果
|
||||
return ApiResponse<PagedResult<PaymentDto>>.Ok(result);
|
||||
}
|
||||
|
||||
@@ -75,7 +75,10 @@ public sealed class PaymentsController(IMediator mediator) : BaseApiController
|
||||
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status404NotFound)]
|
||||
public async Task<ApiResponse<PaymentDto>> Detail(long paymentId, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 查询支付记录详情
|
||||
var result = await mediator.Send(new GetPaymentByIdQuery { PaymentId = paymentId }, cancellationToken);
|
||||
|
||||
// 2. 返回详情或 404
|
||||
return result == null
|
||||
? ApiResponse<PaymentDto>.Error(ErrorCodes.NotFound, "支付记录不存在")
|
||||
: ApiResponse<PaymentDto>.Ok(result);
|
||||
@@ -90,11 +93,16 @@ public sealed class PaymentsController(IMediator mediator) : BaseApiController
|
||||
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status404NotFound)]
|
||||
public async Task<ApiResponse<PaymentDto>> Update(long paymentId, [FromBody] UpdatePaymentCommand command, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 确保命令包含支付记录标识
|
||||
if (command.PaymentId == 0)
|
||||
{
|
||||
command = command with { PaymentId = paymentId };
|
||||
}
|
||||
|
||||
// 2. 执行更新
|
||||
var result = await mediator.Send(command, cancellationToken);
|
||||
|
||||
// 3. 返回更新结果或 404
|
||||
return result == null
|
||||
? ApiResponse<PaymentDto>.Error(ErrorCodes.NotFound, "支付记录不存在")
|
||||
: ApiResponse<PaymentDto>.Ok(result);
|
||||
@@ -109,7 +117,10 @@ public sealed class PaymentsController(IMediator mediator) : BaseApiController
|
||||
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status404NotFound)]
|
||||
public async Task<ApiResponse<object>> Delete(long paymentId, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 执行删除
|
||||
var success = await mediator.Send(new DeletePaymentCommand { PaymentId = paymentId }, cancellationToken);
|
||||
|
||||
// 2. 返回结果或 404
|
||||
return success
|
||||
? ApiResponse<object>.Ok(null)
|
||||
: ApiResponse<object>.Error(ErrorCodes.NotFound, "支付记录不存在");
|
||||
|
||||
@@ -31,7 +31,10 @@ public sealed class PermissionsController(IMediator mediator) : BaseApiControlle
|
||||
[ProducesResponseType(typeof(ApiResponse<PagedResult<PermissionDto>>), StatusCodes.Status200OK)]
|
||||
public async Task<ApiResponse<PagedResult<PermissionDto>>> Search([FromQuery] SearchPermissionsQuery query, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 查询权限分页
|
||||
var result = await mediator.Send(query, cancellationToken);
|
||||
|
||||
// 2. 返回分页数据
|
||||
return ApiResponse<PagedResult<PermissionDto>>.Ok(result);
|
||||
}
|
||||
|
||||
@@ -43,7 +46,10 @@ public sealed class PermissionsController(IMediator mediator) : BaseApiControlle
|
||||
[ProducesResponseType(typeof(ApiResponse<PermissionDto>), StatusCodes.Status200OK)]
|
||||
public async Task<ApiResponse<PermissionDto>> Create([FromBody, Required] CreatePermissionCommand command, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 创建权限
|
||||
var result = await mediator.Send(command, cancellationToken);
|
||||
|
||||
// 2. 返回创建结果
|
||||
return ApiResponse<PermissionDto>.Ok(result);
|
||||
}
|
||||
|
||||
@@ -56,8 +62,13 @@ public sealed class PermissionsController(IMediator mediator) : BaseApiControlle
|
||||
[ProducesResponseType(typeof(ApiResponse<PermissionDto>), StatusCodes.Status404NotFound)]
|
||||
public async Task<ApiResponse<PermissionDto>> Update(long permissionId, [FromBody, Required] UpdatePermissionCommand command, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 绑定权限标识
|
||||
command = command with { PermissionId = permissionId };
|
||||
|
||||
// 2. 执行更新
|
||||
var result = await mediator.Send(command, cancellationToken);
|
||||
|
||||
// 3. 返回更新结果或 404
|
||||
return result is null
|
||||
? ApiResponse<PermissionDto>.Error(StatusCodes.Status404NotFound, "权限不存在")
|
||||
: ApiResponse<PermissionDto>.Ok(result);
|
||||
@@ -71,7 +82,10 @@ public sealed class PermissionsController(IMediator mediator) : BaseApiControlle
|
||||
[ProducesResponseType(typeof(ApiResponse<bool>), StatusCodes.Status200OK)]
|
||||
public async Task<ApiResponse<bool>> Delete(long permissionId, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 构建删除命令
|
||||
var command = new DeletePermissionCommand { PermissionId = permissionId };
|
||||
|
||||
// 2. 执行删除
|
||||
var result = await mediator.Send(command, cancellationToken);
|
||||
return ApiResponse<bool>.Ok(result);
|
||||
}
|
||||
|
||||
@@ -16,16 +16,11 @@ namespace TakeoutSaaS.AdminApi.Controllers;
|
||||
/// <summary>
|
||||
/// 商品管理。
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 初始化控制器。
|
||||
/// </remarks>
|
||||
[ApiVersion("1.0")]
|
||||
[Authorize]
|
||||
[Route("api/admin/v{version:apiVersion}/products")]
|
||||
public sealed class ProductsController(IMediator mediator) : BaseApiController
|
||||
{
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 创建商品。
|
||||
/// </summary>
|
||||
@@ -34,7 +29,10 @@ public sealed class ProductsController(IMediator mediator) : BaseApiController
|
||||
[ProducesResponseType(typeof(ApiResponse<ProductDto>), StatusCodes.Status200OK)]
|
||||
public async Task<ApiResponse<ProductDto>> Create([FromBody] CreateProductCommand command, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 创建商品
|
||||
var result = await mediator.Send(command, cancellationToken);
|
||||
|
||||
// 2. 返回创建结果
|
||||
return ApiResponse<ProductDto>.Ok(result);
|
||||
}
|
||||
|
||||
@@ -54,6 +52,7 @@ public sealed class ProductsController(IMediator mediator) : BaseApiController
|
||||
[FromQuery] bool sortDesc = true,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
// 1. 组装查询参数并执行查询
|
||||
var result = await mediator.Send(new SearchProductsQuery
|
||||
{
|
||||
StoreId = storeId,
|
||||
@@ -65,6 +64,7 @@ public sealed class ProductsController(IMediator mediator) : BaseApiController
|
||||
SortDescending = sortDesc
|
||||
}, cancellationToken);
|
||||
|
||||
// 2. 返回分页结果
|
||||
return ApiResponse<PagedResult<ProductDto>>.Ok(result);
|
||||
}
|
||||
|
||||
@@ -77,7 +77,10 @@ public sealed class ProductsController(IMediator mediator) : BaseApiController
|
||||
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status404NotFound)]
|
||||
public async Task<ApiResponse<ProductDto>> Detail(long productId, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 查询商品详情
|
||||
var result = await mediator.Send(new GetProductByIdQuery { ProductId = productId }, cancellationToken);
|
||||
|
||||
// 2. 返回详情或 404
|
||||
return result == null
|
||||
? ApiResponse<ProductDto>.Error(ErrorCodes.NotFound, "商品不存在")
|
||||
: ApiResponse<ProductDto>.Ok(result);
|
||||
@@ -92,11 +95,16 @@ public sealed class ProductsController(IMediator mediator) : BaseApiController
|
||||
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status404NotFound)]
|
||||
public async Task<ApiResponse<ProductDto>> Update(long productId, [FromBody] UpdateProductCommand command, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 确保命令包含商品标识
|
||||
if (command.ProductId == 0)
|
||||
{
|
||||
command = command with { ProductId = productId };
|
||||
}
|
||||
|
||||
// 2. 执行更新
|
||||
var result = await mediator.Send(command, cancellationToken);
|
||||
|
||||
// 3. 返回更新结果或 404
|
||||
return result == null
|
||||
? ApiResponse<ProductDto>.Error(ErrorCodes.NotFound, "商品不存在")
|
||||
: ApiResponse<ProductDto>.Ok(result);
|
||||
@@ -111,7 +119,10 @@ public sealed class ProductsController(IMediator mediator) : BaseApiController
|
||||
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status404NotFound)]
|
||||
public async Task<ApiResponse<object>> Delete(long productId, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 执行删除
|
||||
var success = await mediator.Send(new DeleteProductCommand { ProductId = productId }, cancellationToken);
|
||||
|
||||
// 2. 返回结果或 404
|
||||
return success
|
||||
? ApiResponse<object>.Ok(null)
|
||||
: ApiResponse<object>.Error(ErrorCodes.NotFound, "商品不存在");
|
||||
|
||||
@@ -32,7 +32,10 @@ public sealed class RolesController(IMediator mediator) : BaseApiController
|
||||
[ProducesResponseType(typeof(ApiResponse<IReadOnlyList<RoleTemplateDto>>), StatusCodes.Status200OK)]
|
||||
public async Task<ApiResponse<IReadOnlyList<RoleTemplateDto>>> ListTemplates([FromQuery] bool? isActive, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 查询模板列表
|
||||
var result = await mediator.Send(new ListRoleTemplatesQuery { IsActive = isActive }, cancellationToken);
|
||||
|
||||
// 2. 返回模板集合
|
||||
return ApiResponse<IReadOnlyList<RoleTemplateDto>>.Ok(result);
|
||||
}
|
||||
|
||||
@@ -48,7 +51,10 @@ public sealed class RolesController(IMediator mediator) : BaseApiController
|
||||
[ProducesResponseType(typeof(ApiResponse<RoleTemplateDto>), StatusCodes.Status404NotFound)]
|
||||
public async Task<ApiResponse<RoleTemplateDto>> GetTemplate(string templateCode, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 查询指定模板
|
||||
var result = await mediator.Send(new GetRoleTemplateQuery { TemplateCode = templateCode }, cancellationToken);
|
||||
|
||||
// 2. 返回模板或 404
|
||||
return result is null
|
||||
? ApiResponse<RoleTemplateDto>.Error(StatusCodes.Status404NotFound, "角色模板不存在")
|
||||
: ApiResponse<RoleTemplateDto>.Ok(result);
|
||||
@@ -62,7 +68,10 @@ public sealed class RolesController(IMediator mediator) : BaseApiController
|
||||
[ProducesResponseType(typeof(ApiResponse<RoleTemplateDto>), StatusCodes.Status200OK)]
|
||||
public async Task<ApiResponse<RoleTemplateDto>> CreateTemplate([FromBody, Required] CreateRoleTemplateCommand command, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 创建模板
|
||||
var result = await mediator.Send(command, cancellationToken);
|
||||
|
||||
// 2. 返回创建结果
|
||||
return ApiResponse<RoleTemplateDto>.Ok(result);
|
||||
}
|
||||
|
||||
@@ -78,8 +87,13 @@ public sealed class RolesController(IMediator mediator) : BaseApiController
|
||||
[FromBody, Required] UpdateRoleTemplateCommand command,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 绑定模板编码
|
||||
command = command with { TemplateCode = templateCode };
|
||||
|
||||
// 2. 执行更新
|
||||
var result = await mediator.Send(command, cancellationToken);
|
||||
|
||||
// 3. 返回更新结果或 404
|
||||
return result is null
|
||||
? ApiResponse<RoleTemplateDto>.Error(StatusCodes.Status404NotFound, "角色模板不存在")
|
||||
: ApiResponse<RoleTemplateDto>.Ok(result);
|
||||
@@ -93,7 +107,10 @@ public sealed class RolesController(IMediator mediator) : BaseApiController
|
||||
[ProducesResponseType(typeof(ApiResponse<bool>), StatusCodes.Status200OK)]
|
||||
public async Task<ApiResponse<bool>> DeleteTemplate(string templateCode, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 删除模板
|
||||
var result = await mediator.Send(new DeleteRoleTemplateCommand { TemplateCode = templateCode }, cancellationToken);
|
||||
|
||||
// 2. 返回执行结果
|
||||
return ApiResponse<bool>.Ok(result);
|
||||
}
|
||||
|
||||
@@ -112,7 +129,10 @@ public sealed class RolesController(IMediator mediator) : BaseApiController
|
||||
[FromBody, Required] CopyRoleTemplateCommand command,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 绑定模板编码
|
||||
command = command with { TemplateCode = templateCode };
|
||||
|
||||
// 2. 复制模板并返回角色
|
||||
var result = await mediator.Send(command, cancellationToken);
|
||||
return ApiResponse<RoleDto>.Ok(result);
|
||||
}
|
||||
@@ -131,7 +151,10 @@ public sealed class RolesController(IMediator mediator) : BaseApiController
|
||||
[FromBody] InitializeRoleTemplatesCommand? command,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 确保命令实例存在
|
||||
command ??= new InitializeRoleTemplatesCommand();
|
||||
|
||||
// 2. 执行初始化
|
||||
var result = await mediator.Send(command, cancellationToken);
|
||||
return ApiResponse<IReadOnlyList<RoleDto>>.Ok(result);
|
||||
}
|
||||
@@ -149,7 +172,10 @@ public sealed class RolesController(IMediator mediator) : BaseApiController
|
||||
[ProducesResponseType(typeof(ApiResponse<PagedResult<RoleDto>>), StatusCodes.Status200OK)]
|
||||
public async Task<ApiResponse<PagedResult<RoleDto>>> Search([FromQuery] SearchRolesQuery query, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 查询角色分页
|
||||
var result = await mediator.Send(query, cancellationToken);
|
||||
|
||||
// 2. 返回分页数据
|
||||
return ApiResponse<PagedResult<RoleDto>>.Ok(result);
|
||||
}
|
||||
|
||||
@@ -161,7 +187,10 @@ public sealed class RolesController(IMediator mediator) : BaseApiController
|
||||
[ProducesResponseType(typeof(ApiResponse<RoleDto>), StatusCodes.Status200OK)]
|
||||
public async Task<ApiResponse<RoleDto>> Create([FromBody, Required] CreateRoleCommand command, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 创建角色
|
||||
var result = await mediator.Send(command, cancellationToken);
|
||||
|
||||
// 2. 返回创建结果
|
||||
return ApiResponse<RoleDto>.Ok(result);
|
||||
}
|
||||
|
||||
@@ -174,8 +203,13 @@ public sealed class RolesController(IMediator mediator) : BaseApiController
|
||||
[ProducesResponseType(typeof(ApiResponse<RoleDto>), StatusCodes.Status404NotFound)]
|
||||
public async Task<ApiResponse<RoleDto>> Update(long roleId, [FromBody, Required] UpdateRoleCommand command, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 绑定角色标识
|
||||
command = command with { RoleId = roleId };
|
||||
|
||||
// 2. 执行更新
|
||||
var result = await mediator.Send(command, cancellationToken);
|
||||
|
||||
// 3. 返回更新结果或 404
|
||||
return result is null
|
||||
? ApiResponse<RoleDto>.Error(StatusCodes.Status404NotFound, "角色不存在")
|
||||
: ApiResponse<RoleDto>.Ok(result);
|
||||
@@ -189,7 +223,10 @@ public sealed class RolesController(IMediator mediator) : BaseApiController
|
||||
[ProducesResponseType(typeof(ApiResponse<bool>), StatusCodes.Status200OK)]
|
||||
public async Task<ApiResponse<bool>> Delete(long roleId, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 构建删除命令
|
||||
var command = new DeleteRoleCommand { RoleId = roleId };
|
||||
|
||||
// 2. 执行删除
|
||||
var result = await mediator.Send(command, cancellationToken);
|
||||
return ApiResponse<bool>.Ok(result);
|
||||
}
|
||||
@@ -202,7 +239,10 @@ public sealed class RolesController(IMediator mediator) : BaseApiController
|
||||
[ProducesResponseType(typeof(ApiResponse<bool>), StatusCodes.Status200OK)]
|
||||
public async Task<ApiResponse<bool>> BindPermissions(long roleId, [FromBody, Required] BindRolePermissionsCommand command, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 绑定角色标识
|
||||
command = command with { RoleId = roleId };
|
||||
|
||||
// 2. 执行覆盖式授权
|
||||
var result = await mediator.Send(command, cancellationToken);
|
||||
return ApiResponse<bool>.Ok(result);
|
||||
}
|
||||
|
||||
@@ -16,16 +16,11 @@ namespace TakeoutSaaS.AdminApi.Controllers;
|
||||
/// <summary>
|
||||
/// 门店管理。
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 初始化控制器。
|
||||
/// </remarks>
|
||||
[ApiVersion("1.0")]
|
||||
[Authorize]
|
||||
[Route("api/admin/v{version:apiVersion}/stores")]
|
||||
public sealed class StoresController(IMediator mediator) : BaseApiController
|
||||
{
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 创建门店。
|
||||
/// </summary>
|
||||
@@ -34,7 +29,10 @@ public sealed class StoresController(IMediator mediator) : BaseApiController
|
||||
[ProducesResponseType(typeof(ApiResponse<StoreDto>), StatusCodes.Status200OK)]
|
||||
public async Task<ApiResponse<StoreDto>> Create([FromBody] CreateStoreCommand command, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 创建门店
|
||||
var result = await mediator.Send(command, cancellationToken);
|
||||
|
||||
// 2. 返回创建结果
|
||||
return ApiResponse<StoreDto>.Ok(result);
|
||||
}
|
||||
|
||||
@@ -53,6 +51,7 @@ public sealed class StoresController(IMediator mediator) : BaseApiController
|
||||
[FromQuery] bool sortDesc = true,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
// 1. 组装查询参数并执行查询
|
||||
var result = await mediator.Send(new SearchStoresQuery
|
||||
{
|
||||
MerchantId = merchantId,
|
||||
@@ -63,6 +62,7 @@ public sealed class StoresController(IMediator mediator) : BaseApiController
|
||||
SortDescending = sortDesc
|
||||
}, cancellationToken);
|
||||
|
||||
// 2. 返回分页结果
|
||||
return ApiResponse<PagedResult<StoreDto>>.Ok(result);
|
||||
}
|
||||
|
||||
@@ -75,7 +75,10 @@ public sealed class StoresController(IMediator mediator) : BaseApiController
|
||||
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status404NotFound)]
|
||||
public async Task<ApiResponse<StoreDto>> Detail(long storeId, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 查询门店详情
|
||||
var result = await mediator.Send(new GetStoreByIdQuery { StoreId = storeId }, cancellationToken);
|
||||
|
||||
// 2. 返回详情或 404
|
||||
return result == null
|
||||
? ApiResponse<StoreDto>.Error(ErrorCodes.NotFound, "门店不存在")
|
||||
: ApiResponse<StoreDto>.Ok(result);
|
||||
@@ -90,11 +93,16 @@ public sealed class StoresController(IMediator mediator) : BaseApiController
|
||||
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status404NotFound)]
|
||||
public async Task<ApiResponse<StoreDto>> Update(long storeId, [FromBody] UpdateStoreCommand command, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 确保命令包含门店标识
|
||||
if (command.StoreId == 0)
|
||||
{
|
||||
command = command with { StoreId = storeId };
|
||||
}
|
||||
|
||||
// 2. 执行更新
|
||||
var result = await mediator.Send(command, cancellationToken);
|
||||
|
||||
// 3. 返回更新结果或 404
|
||||
return result == null
|
||||
? ApiResponse<StoreDto>.Error(ErrorCodes.NotFound, "门店不存在")
|
||||
: ApiResponse<StoreDto>.Ok(result);
|
||||
@@ -109,7 +117,10 @@ public sealed class StoresController(IMediator mediator) : BaseApiController
|
||||
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status404NotFound)]
|
||||
public async Task<ApiResponse<object>> Delete(long storeId, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 执行删除
|
||||
var success = await mediator.Send(new DeleteStoreCommand { StoreId = storeId }, cancellationToken);
|
||||
|
||||
// 2. 返回结果或 404
|
||||
return success
|
||||
? ApiResponse<object>.Ok(null)
|
||||
: ApiResponse<object>.Error(ErrorCodes.NotFound, "门店不存在");
|
||||
|
||||
@@ -31,7 +31,10 @@ public sealed class SystemParametersController(IMediator mediator) : BaseApiCont
|
||||
[ProducesResponseType(typeof(ApiResponse<SystemParameterDto>), StatusCodes.Status200OK)]
|
||||
public async Task<ApiResponse<SystemParameterDto>> Create([FromBody] CreateSystemParameterCommand command, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 创建系统参数
|
||||
var result = await mediator.Send(command, cancellationToken);
|
||||
|
||||
// 2. 返回创建结果
|
||||
return ApiResponse<SystemParameterDto>.Ok(result);
|
||||
}
|
||||
|
||||
@@ -50,6 +53,7 @@ public sealed class SystemParametersController(IMediator mediator) : BaseApiCont
|
||||
[FromQuery] bool sortDesc = true,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
// 1. 组合查询参数
|
||||
var result = await mediator.Send(new SearchSystemParametersQuery
|
||||
{
|
||||
Keyword = keyword,
|
||||
@@ -60,6 +64,7 @@ public sealed class SystemParametersController(IMediator mediator) : BaseApiCont
|
||||
SortDescending = sortDesc
|
||||
}, cancellationToken);
|
||||
|
||||
// 2. 返回分页结果
|
||||
return ApiResponse<PagedResult<SystemParameterDto>>.Ok(result);
|
||||
}
|
||||
|
||||
@@ -72,7 +77,10 @@ public sealed class SystemParametersController(IMediator mediator) : BaseApiCont
|
||||
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status404NotFound)]
|
||||
public async Task<ApiResponse<SystemParameterDto>> Detail(long parameterId, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 查询参数详情
|
||||
var result = await mediator.Send(new GetSystemParameterByIdQuery(parameterId), cancellationToken);
|
||||
|
||||
// 2. 返回详情或 404
|
||||
return result == null
|
||||
? ApiResponse<SystemParameterDto>.Error(ErrorCodes.NotFound, "系统参数不存在")
|
||||
: ApiResponse<SystemParameterDto>.Ok(result);
|
||||
@@ -87,12 +95,16 @@ public sealed class SystemParametersController(IMediator mediator) : BaseApiCont
|
||||
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status404NotFound)]
|
||||
public async Task<ApiResponse<SystemParameterDto>> Update(long parameterId, [FromBody] UpdateSystemParameterCommand command, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 确保命令包含参数标识
|
||||
if (command.ParameterId == 0)
|
||||
{
|
||||
command = command with { ParameterId = parameterId };
|
||||
}
|
||||
|
||||
// 2. 执行更新
|
||||
var result = await mediator.Send(command, cancellationToken);
|
||||
|
||||
// 3. 返回结果或 404
|
||||
return result == null
|
||||
? ApiResponse<SystemParameterDto>.Error(ErrorCodes.NotFound, "系统参数不存在")
|
||||
: ApiResponse<SystemParameterDto>.Ok(result);
|
||||
@@ -107,7 +119,10 @@ public sealed class SystemParametersController(IMediator mediator) : BaseApiCont
|
||||
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status404NotFound)]
|
||||
public async Task<ApiResponse<object>> Delete(long parameterId, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 执行删除
|
||||
var success = await mediator.Send(new DeleteSystemParameterCommand { ParameterId = parameterId }, cancellationToken);
|
||||
|
||||
// 2. 返回成功或 404
|
||||
return success
|
||||
? ApiResponse.Success()
|
||||
: ApiResponse<object>.Error(ErrorCodes.NotFound, "系统参数不存在");
|
||||
|
||||
@@ -28,8 +28,13 @@ public sealed class TenantAnnouncementsController(IMediator mediator) : BaseApiC
|
||||
[ProducesResponseType(typeof(ApiResponse<PagedResult<TenantAnnouncementDto>>), StatusCodes.Status200OK)]
|
||||
public async Task<ApiResponse<PagedResult<TenantAnnouncementDto>>> Search(long tenantId, [FromQuery] SearchTenantAnnouncementsQuery query, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 绑定租户标识
|
||||
query = query with { TenantId = tenantId };
|
||||
|
||||
// 2. 查询公告列表
|
||||
var result = await mediator.Send(query, cancellationToken);
|
||||
|
||||
// 3. 返回分页结果
|
||||
return ApiResponse<PagedResult<TenantAnnouncementDto>>.Ok(result);
|
||||
}
|
||||
|
||||
@@ -42,7 +47,10 @@ public sealed class TenantAnnouncementsController(IMediator mediator) : BaseApiC
|
||||
[ProducesResponseType(typeof(ApiResponse<TenantAnnouncementDto>), StatusCodes.Status404NotFound)]
|
||||
public async Task<ApiResponse<TenantAnnouncementDto>> Detail(long tenantId, long announcementId, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 查询指定公告
|
||||
var result = await mediator.Send(new GetTenantAnnouncementQuery { TenantId = tenantId, AnnouncementId = announcementId }, cancellationToken);
|
||||
|
||||
// 2. 返回详情或 404
|
||||
return result is null
|
||||
? ApiResponse<TenantAnnouncementDto>.Error(StatusCodes.Status404NotFound, "公告不存在")
|
||||
: ApiResponse<TenantAnnouncementDto>.Ok(result);
|
||||
@@ -56,7 +64,10 @@ public sealed class TenantAnnouncementsController(IMediator mediator) : BaseApiC
|
||||
[ProducesResponseType(typeof(ApiResponse<TenantAnnouncementDto>), StatusCodes.Status200OK)]
|
||||
public async Task<ApiResponse<TenantAnnouncementDto>> Create(long tenantId, [FromBody, Required] CreateTenantAnnouncementCommand command, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 绑定租户标识
|
||||
command = command with { TenantId = tenantId };
|
||||
|
||||
// 2. 创建公告并返回
|
||||
var result = await mediator.Send(command, cancellationToken);
|
||||
return ApiResponse<TenantAnnouncementDto>.Ok(result);
|
||||
}
|
||||
@@ -70,8 +81,13 @@ public sealed class TenantAnnouncementsController(IMediator mediator) : BaseApiC
|
||||
[ProducesResponseType(typeof(ApiResponse<TenantAnnouncementDto>), StatusCodes.Status404NotFound)]
|
||||
public async Task<ApiResponse<TenantAnnouncementDto>> Update(long tenantId, long announcementId, [FromBody, Required] UpdateTenantAnnouncementCommand command, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 绑定租户与公告标识
|
||||
command = command with { TenantId = tenantId, AnnouncementId = announcementId };
|
||||
|
||||
// 2. 执行更新
|
||||
var result = await mediator.Send(command, cancellationToken);
|
||||
|
||||
// 3. 返回更新结果或 404
|
||||
return result is null
|
||||
? ApiResponse<TenantAnnouncementDto>.Error(StatusCodes.Status404NotFound, "公告不存在")
|
||||
: ApiResponse<TenantAnnouncementDto>.Ok(result);
|
||||
@@ -85,7 +101,10 @@ public sealed class TenantAnnouncementsController(IMediator mediator) : BaseApiC
|
||||
[ProducesResponseType(typeof(ApiResponse<bool>), StatusCodes.Status200OK)]
|
||||
public async Task<ApiResponse<bool>> Delete(long tenantId, long announcementId, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 删除公告
|
||||
var result = await mediator.Send(new DeleteTenantAnnouncementCommand { TenantId = tenantId, AnnouncementId = announcementId }, cancellationToken);
|
||||
|
||||
// 2. 返回执行结果
|
||||
return ApiResponse<bool>.Ok(result);
|
||||
}
|
||||
|
||||
@@ -98,7 +117,10 @@ public sealed class TenantAnnouncementsController(IMediator mediator) : BaseApiC
|
||||
[ProducesResponseType(typeof(ApiResponse<TenantAnnouncementDto>), StatusCodes.Status404NotFound)]
|
||||
public async Task<ApiResponse<TenantAnnouncementDto>> MarkRead(long tenantId, long announcementId, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 标记公告已读
|
||||
var result = await mediator.Send(new MarkTenantAnnouncementReadCommand { TenantId = tenantId, AnnouncementId = announcementId }, cancellationToken);
|
||||
|
||||
// 2. 返回结果或 404
|
||||
return result is null
|
||||
? ApiResponse<TenantAnnouncementDto>.Error(StatusCodes.Status404NotFound, "公告不存在")
|
||||
: ApiResponse<TenantAnnouncementDto>.Ok(result);
|
||||
|
||||
@@ -28,8 +28,13 @@ public sealed class TenantBillingsController(IMediator mediator) : BaseApiContro
|
||||
[ProducesResponseType(typeof(ApiResponse<PagedResult<TenantBillingDto>>), StatusCodes.Status200OK)]
|
||||
public async Task<ApiResponse<PagedResult<TenantBillingDto>>> Search(long tenantId, [FromQuery] SearchTenantBillsQuery query, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 绑定租户标识
|
||||
query = query with { TenantId = tenantId };
|
||||
|
||||
// 2. 查询账单列表
|
||||
var result = await mediator.Send(query, cancellationToken);
|
||||
|
||||
// 3. 返回分页结果
|
||||
return ApiResponse<PagedResult<TenantBillingDto>>.Ok(result);
|
||||
}
|
||||
|
||||
@@ -42,7 +47,10 @@ public sealed class TenantBillingsController(IMediator mediator) : BaseApiContro
|
||||
[ProducesResponseType(typeof(ApiResponse<TenantBillingDto>), StatusCodes.Status404NotFound)]
|
||||
public async Task<ApiResponse<TenantBillingDto>> Detail(long tenantId, long billingId, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 查询账单详情
|
||||
var result = await mediator.Send(new GetTenantBillQuery { TenantId = tenantId, BillingId = billingId }, cancellationToken);
|
||||
|
||||
// 2. 返回详情或 404
|
||||
return result is null
|
||||
? ApiResponse<TenantBillingDto>.Error(StatusCodes.Status404NotFound, "账单不存在")
|
||||
: ApiResponse<TenantBillingDto>.Ok(result);
|
||||
@@ -56,7 +64,10 @@ public sealed class TenantBillingsController(IMediator mediator) : BaseApiContro
|
||||
[ProducesResponseType(typeof(ApiResponse<TenantBillingDto>), StatusCodes.Status200OK)]
|
||||
public async Task<ApiResponse<TenantBillingDto>> Create(long tenantId, [FromBody, Required] CreateTenantBillingCommand command, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 绑定租户标识
|
||||
command = command with { TenantId = tenantId };
|
||||
|
||||
// 2. 创建账单
|
||||
var result = await mediator.Send(command, cancellationToken);
|
||||
return ApiResponse<TenantBillingDto>.Ok(result);
|
||||
}
|
||||
@@ -70,8 +81,13 @@ public sealed class TenantBillingsController(IMediator mediator) : BaseApiContro
|
||||
[ProducesResponseType(typeof(ApiResponse<TenantBillingDto>), StatusCodes.Status404NotFound)]
|
||||
public async Task<ApiResponse<TenantBillingDto>> MarkPaid(long tenantId, long billingId, [FromBody, Required] MarkTenantBillingPaidCommand command, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 绑定租户与账单标识
|
||||
command = command with { TenantId = tenantId, BillingId = billingId };
|
||||
|
||||
// 2. 标记支付状态
|
||||
var result = await mediator.Send(command, cancellationToken);
|
||||
|
||||
// 3. 返回结果或 404
|
||||
return result is null
|
||||
? ApiResponse<TenantBillingDto>.Error(StatusCodes.Status404NotFound, "账单不存在")
|
||||
: ApiResponse<TenantBillingDto>.Ok(result);
|
||||
|
||||
@@ -27,8 +27,13 @@ public sealed class TenantNotificationsController(IMediator mediator) : BaseApiC
|
||||
[ProducesResponseType(typeof(ApiResponse<PagedResult<TenantNotificationDto>>), StatusCodes.Status200OK)]
|
||||
public async Task<ApiResponse<PagedResult<TenantNotificationDto>>> Search(long tenantId, [FromQuery] SearchTenantNotificationsQuery query, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 绑定租户标识
|
||||
query = query with { TenantId = tenantId };
|
||||
|
||||
// 2. 查询通知列表
|
||||
var result = await mediator.Send(query, cancellationToken);
|
||||
|
||||
// 3. 返回分页结果
|
||||
return ApiResponse<PagedResult<TenantNotificationDto>>.Ok(result);
|
||||
}
|
||||
|
||||
@@ -41,7 +46,10 @@ public sealed class TenantNotificationsController(IMediator mediator) : BaseApiC
|
||||
[ProducesResponseType(typeof(ApiResponse<TenantNotificationDto>), StatusCodes.Status404NotFound)]
|
||||
public async Task<ApiResponse<TenantNotificationDto>> MarkRead(long tenantId, long notificationId, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 标记通知为已读
|
||||
var result = await mediator.Send(new MarkTenantNotificationReadCommand { TenantId = tenantId, NotificationId = notificationId }, cancellationToken);
|
||||
|
||||
// 2. 返回结果或 404
|
||||
return result is null
|
||||
? ApiResponse<TenantNotificationDto>.Error(StatusCodes.Status404NotFound, "通知不存在")
|
||||
: ApiResponse<TenantNotificationDto>.Ok(result);
|
||||
|
||||
@@ -28,7 +28,10 @@ public sealed class TenantPackagesController(IMediator mediator) : BaseApiContro
|
||||
[ProducesResponseType(typeof(ApiResponse<PagedResult<TenantPackageDto>>), StatusCodes.Status200OK)]
|
||||
public async Task<ApiResponse<PagedResult<TenantPackageDto>>> Search([FromQuery] SearchTenantPackagesQuery query, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 查询租户套餐分页
|
||||
var result = await mediator.Send(query, cancellationToken);
|
||||
|
||||
// 2. 返回结果
|
||||
return ApiResponse<PagedResult<TenantPackageDto>>.Ok(result);
|
||||
}
|
||||
|
||||
@@ -41,7 +44,10 @@ public sealed class TenantPackagesController(IMediator mediator) : BaseApiContro
|
||||
[ProducesResponseType(typeof(ApiResponse<TenantPackageDto>), StatusCodes.Status404NotFound)]
|
||||
public async Task<ApiResponse<TenantPackageDto>> Detail(long tenantPackageId, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 查询套餐详情
|
||||
var result = await mediator.Send(new GetTenantPackageByIdQuery { TenantPackageId = tenantPackageId }, cancellationToken);
|
||||
|
||||
// 2. 返回查询结果或 404
|
||||
return result is null
|
||||
? ApiResponse<TenantPackageDto>.Error(StatusCodes.Status404NotFound, "套餐不存在")
|
||||
: ApiResponse<TenantPackageDto>.Ok(result);
|
||||
@@ -55,7 +61,10 @@ public sealed class TenantPackagesController(IMediator mediator) : BaseApiContro
|
||||
[ProducesResponseType(typeof(ApiResponse<TenantPackageDto>), StatusCodes.Status200OK)]
|
||||
public async Task<ApiResponse<TenantPackageDto>> Create([FromBody, Required] CreateTenantPackageCommand command, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 执行创建
|
||||
var result = await mediator.Send(command, cancellationToken);
|
||||
|
||||
// 2. 返回创建结果
|
||||
return ApiResponse<TenantPackageDto>.Ok(result);
|
||||
}
|
||||
|
||||
@@ -68,8 +77,13 @@ public sealed class TenantPackagesController(IMediator mediator) : BaseApiContro
|
||||
[ProducesResponseType(typeof(ApiResponse<TenantPackageDto>), StatusCodes.Status404NotFound)]
|
||||
public async Task<ApiResponse<TenantPackageDto>> Update(long tenantPackageId, [FromBody, Required] UpdateTenantPackageCommand command, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 绑定路由 ID
|
||||
command = command with { TenantPackageId = tenantPackageId };
|
||||
|
||||
// 2. 执行更新
|
||||
var result = await mediator.Send(command, cancellationToken);
|
||||
|
||||
// 3. 返回更新结果或 404
|
||||
return result is null
|
||||
? ApiResponse<TenantPackageDto>.Error(StatusCodes.Status404NotFound, "套餐不存在")
|
||||
: ApiResponse<TenantPackageDto>.Ok(result);
|
||||
@@ -83,7 +97,10 @@ public sealed class TenantPackagesController(IMediator mediator) : BaseApiContro
|
||||
[ProducesResponseType(typeof(ApiResponse<bool>), StatusCodes.Status200OK)]
|
||||
public async Task<ApiResponse<bool>> Delete(long tenantPackageId, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 构建删除命令
|
||||
var command = new DeleteTenantPackageCommand { TenantPackageId = tenantPackageId };
|
||||
|
||||
// 2. 执行删除并返回
|
||||
var result = await mediator.Send(command, cancellationToken);
|
||||
return ApiResponse<bool>.Ok(result);
|
||||
}
|
||||
|
||||
@@ -29,7 +29,10 @@ public sealed class TenantsController(IMediator mediator) : BaseApiController
|
||||
[ProducesResponseType(typeof(ApiResponse<TenantDto>), StatusCodes.Status200OK)]
|
||||
public async Task<ApiResponse<TenantDto>> Register([FromBody] RegisterTenantCommand command, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 注册租户并初始化套餐
|
||||
var result = await mediator.Send(command, cancellationToken);
|
||||
|
||||
// 2. 返回注册结果
|
||||
return ApiResponse<TenantDto>.Ok(result);
|
||||
}
|
||||
|
||||
@@ -41,7 +44,10 @@ public sealed class TenantsController(IMediator mediator) : BaseApiController
|
||||
[ProducesResponseType(typeof(ApiResponse<PagedResult<TenantDto>>), StatusCodes.Status200OK)]
|
||||
public async Task<ApiResponse<PagedResult<TenantDto>>> Search([FromQuery] SearchTenantsQuery query, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 查询租户分页
|
||||
var result = await mediator.Send(query, cancellationToken);
|
||||
|
||||
// 2. 返回分页数据
|
||||
return ApiResponse<PagedResult<TenantDto>>.Ok(result);
|
||||
}
|
||||
|
||||
@@ -53,7 +59,10 @@ public sealed class TenantsController(IMediator mediator) : BaseApiController
|
||||
[ProducesResponseType(typeof(ApiResponse<TenantDetailDto>), StatusCodes.Status200OK)]
|
||||
public async Task<ApiResponse<TenantDetailDto>> Detail(long tenantId, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 查询租户详情
|
||||
var result = await mediator.Send(new GetTenantByIdQuery(tenantId), cancellationToken);
|
||||
|
||||
// 2. 返回租户信息
|
||||
return ApiResponse<TenantDetailDto>.Ok(result);
|
||||
}
|
||||
|
||||
@@ -68,8 +77,13 @@ public sealed class TenantsController(IMediator mediator) : BaseApiController
|
||||
[FromBody] SubmitTenantVerificationCommand body,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 合并路由中的租户标识
|
||||
var command = body with { TenantId = tenantId };
|
||||
|
||||
// 2. 提交或更新认证资料
|
||||
var result = await mediator.Send(command, cancellationToken);
|
||||
|
||||
// 3. 返回认证结果
|
||||
return ApiResponse<TenantVerificationDto>.Ok(result);
|
||||
}
|
||||
|
||||
@@ -81,8 +95,13 @@ public sealed class TenantsController(IMediator mediator) : BaseApiController
|
||||
[ProducesResponseType(typeof(ApiResponse<TenantDto>), StatusCodes.Status200OK)]
|
||||
public async Task<ApiResponse<TenantDto>> Review(long tenantId, [FromBody] ReviewTenantCommand body, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 绑定租户标识
|
||||
var command = body with { TenantId = tenantId };
|
||||
|
||||
// 2. 执行审核
|
||||
var result = await mediator.Send(command, cancellationToken);
|
||||
|
||||
// 3. 返回审核结果
|
||||
return ApiResponse<TenantDto>.Ok(result);
|
||||
}
|
||||
|
||||
@@ -97,7 +116,10 @@ public sealed class TenantsController(IMediator mediator) : BaseApiController
|
||||
[FromBody] CreateTenantSubscriptionCommand body,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 绑定租户并创建或续费订阅
|
||||
var command = body with { TenantId = tenantId };
|
||||
|
||||
// 2. 返回订阅结果
|
||||
var result = await mediator.Send(command, cancellationToken);
|
||||
return ApiResponse<TenantSubscriptionDto>.Ok(result);
|
||||
}
|
||||
@@ -114,8 +136,13 @@ public sealed class TenantsController(IMediator mediator) : BaseApiController
|
||||
[FromBody] ChangeTenantSubscriptionPlanCommand body,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 绑定租户与订阅标识
|
||||
var command = body with { TenantId = tenantId, TenantSubscriptionId = subscriptionId };
|
||||
|
||||
// 2. 执行升降配
|
||||
var result = await mediator.Send(command, cancellationToken);
|
||||
|
||||
// 3. 返回调整后的订阅
|
||||
return ApiResponse<TenantSubscriptionDto>.Ok(result);
|
||||
}
|
||||
|
||||
@@ -131,7 +158,10 @@ public sealed class TenantsController(IMediator mediator) : BaseApiController
|
||||
[FromQuery] int pageSize = 20,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
// 1. 构造审核日志查询
|
||||
var query = new GetTenantAuditLogsQuery(tenantId, page, pageSize);
|
||||
|
||||
// 2. 查询并返回分页结果
|
||||
var result = await mediator.Send(query, cancellationToken);
|
||||
return ApiResponse<PagedResult<TenantAuditLogDto>>.Ok(result);
|
||||
}
|
||||
@@ -148,7 +178,10 @@ public sealed class TenantsController(IMediator mediator) : BaseApiController
|
||||
[FromBody, Required] CheckTenantQuotaCommand body,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 绑定租户标识
|
||||
var command = body with { TenantId = tenantId };
|
||||
|
||||
// 2. 校验并占用配额
|
||||
var result = await mediator.Send(command, cancellationToken);
|
||||
return ApiResponse<QuotaCheckResultDto>.Ok(result);
|
||||
}
|
||||
|
||||
@@ -58,6 +58,7 @@ public sealed class UserPermissionsController(IAdminAuthService authService) : B
|
||||
[FromQuery] SearchUserPermissionsQuery query,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 查询当前租户的用户权限概览
|
||||
var result = await authService.SearchUserPermissionsAsync(
|
||||
query.Keyword,
|
||||
query.Page,
|
||||
@@ -66,6 +67,7 @@ public sealed class UserPermissionsController(IAdminAuthService authService) : B
|
||||
query.SortDescending,
|
||||
cancellationToken);
|
||||
|
||||
// 2. 返回分页结果
|
||||
return ApiResponse<PagedResult<UserPermissionDto>>.Ok(result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,13 +26,16 @@ using TakeoutSaaS.Module.Tenancy.Extensions;
|
||||
using TakeoutSaaS.Shared.Web.Extensions;
|
||||
using TakeoutSaaS.Shared.Web.Swagger;
|
||||
|
||||
// 1. 创建构建器与日志模板
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
const string logTemplate = "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} {Level:u3}] [TraceId:{TraceId}] [SpanId:{SpanId}] [Service:{Service}] {SourceContext} {Message:lj}{NewLine}{Exception}";
|
||||
|
||||
// 2. 加载种子配置文件
|
||||
builder.Configuration
|
||||
.AddJsonFile("appsettings.Seed.json", optional: true, reloadOnChange: true)
|
||||
.AddJsonFile($"appsettings.Seed.{builder.Environment.EnvironmentName}.json", optional: true, reloadOnChange: true);
|
||||
|
||||
// 3. 配置 Serilog 输出
|
||||
builder.Host.UseSerilog((context, _, configuration) =>
|
||||
{
|
||||
configuration
|
||||
@@ -47,6 +50,7 @@ builder.Host.UseSerilog((context, _, configuration) =>
|
||||
outputTemplate: logTemplate);
|
||||
});
|
||||
|
||||
// 4. 注册通用 Web 能力与 Swagger
|
||||
builder.Services.AddSharedWebCore();
|
||||
builder.Services.AddSharedSwagger(options =>
|
||||
{
|
||||
@@ -54,6 +58,8 @@ builder.Services.AddSharedSwagger(options =>
|
||||
options.Description = "管理后台 API 文档";
|
||||
options.EnableAuthorization = true;
|
||||
});
|
||||
|
||||
// 5. 注册领域与基础设施模块
|
||||
builder.Services.AddIdentityApplication();
|
||||
builder.Services.AddIdentityInfrastructure(builder.Configuration, enableAdminSeed: true);
|
||||
builder.Services.AddAppInfrastructure(builder.Configuration);
|
||||
@@ -71,6 +77,8 @@ builder.Services.AddMessagingModule(builder.Configuration);
|
||||
builder.Services.AddMessagingApplication();
|
||||
builder.Services.AddSchedulerModule(builder.Configuration);
|
||||
builder.Services.AddHealthChecks();
|
||||
|
||||
// 6. 配置 OpenTelemetry 采集
|
||||
var otelSection = builder.Configuration.GetSection("Otel");
|
||||
var otelEndpoint = otelSection.GetValue<string>("Endpoint");
|
||||
var useConsoleExporter = otelSection.GetValue<bool?>("UseConsoleExporter") ?? builder.Environment.IsDevelopment();
|
||||
@@ -86,7 +94,6 @@ builder.Services.AddOpenTelemetry()
|
||||
.AddAspNetCoreInstrumentation()
|
||||
.AddHttpClientInstrumentation()
|
||||
.AddEntityFrameworkCoreInstrumentation();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(otelEndpoint))
|
||||
{
|
||||
tracing.AddOtlpExporter(exporter =>
|
||||
@@ -94,7 +101,6 @@ builder.Services.AddOpenTelemetry()
|
||||
exporter.Endpoint = new Uri(otelEndpoint);
|
||||
});
|
||||
}
|
||||
|
||||
if (useConsoleExporter)
|
||||
{
|
||||
tracing.AddConsoleExporter();
|
||||
@@ -107,7 +113,6 @@ builder.Services.AddOpenTelemetry()
|
||||
.AddHttpClientInstrumentation()
|
||||
.AddRuntimeInstrumentation()
|
||||
.AddPrometheusExporter();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(otelEndpoint))
|
||||
{
|
||||
metrics.AddOtlpExporter(exporter =>
|
||||
@@ -115,13 +120,13 @@ builder.Services.AddOpenTelemetry()
|
||||
exporter.Endpoint = new Uri(otelEndpoint);
|
||||
});
|
||||
}
|
||||
|
||||
if (useConsoleExporter)
|
||||
{
|
||||
metrics.AddConsoleExporter();
|
||||
}
|
||||
});
|
||||
|
||||
// 7. 解析并配置 CORS
|
||||
var adminOrigins = ResolveCorsOrigins(builder.Configuration, "Cors:Admin");
|
||||
builder.Services.AddCors(options =>
|
||||
{
|
||||
@@ -131,8 +136,8 @@ builder.Services.AddCors(options =>
|
||||
});
|
||||
});
|
||||
|
||||
// 8. 构建应用并配置中间件管道
|
||||
var app = builder.Build();
|
||||
|
||||
app.UseCors("AdminApiCors");
|
||||
app.UseTenantResolution();
|
||||
app.UseSharedWebCore();
|
||||
@@ -140,12 +145,12 @@ app.UseAuthentication();
|
||||
app.UseAuthorization();
|
||||
app.UseSharedSwagger();
|
||||
app.UseSchedulerDashboard(builder.Configuration);
|
||||
|
||||
app.MapHealthChecks("/healthz");
|
||||
app.MapPrometheusScrapingEndpoint();
|
||||
app.MapControllers();
|
||||
app.Run();
|
||||
|
||||
// 9. 解析配置中的 CORS 域名
|
||||
static string[] ResolveCorsOrigins(IConfiguration configuration, string sectionKey)
|
||||
{
|
||||
var origins = configuration.GetSection(sectionKey).Get<string[]>();
|
||||
@@ -155,6 +160,7 @@ static string[] ResolveCorsOrigins(IConfiguration configuration, string sectionK
|
||||
.ToArray() ?? [];
|
||||
}
|
||||
|
||||
// 10. 构建 CORS 策略
|
||||
static void ConfigureCorsPolicy(CorsPolicyBuilder policy, string[] origins)
|
||||
{
|
||||
if (origins.Length == 0)
|
||||
@@ -166,7 +172,6 @@ static void ConfigureCorsPolicy(CorsPolicyBuilder policy, string[] origins)
|
||||
policy.WithOrigins(origins)
|
||||
.AllowCredentials();
|
||||
}
|
||||
|
||||
policy
|
||||
.AllowAnyHeader()
|
||||
.AllowAnyMethod();
|
||||
|
||||
@@ -10,17 +10,13 @@ namespace TakeoutSaaS.MiniApi.Controllers;
|
||||
/// <summary>
|
||||
/// 小程序登录认证
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 小程序登录认证
|
||||
/// </remarks>
|
||||
/// <param name="authService"></param>
|
||||
/// <remarks>提供小程序端的微信登录与 Token 刷新能力。</remarks>
|
||||
/// <param name="authService">小程序认证服务</param>
|
||||
[ApiVersion("1.0")]
|
||||
[Authorize]
|
||||
[Route("api/mini/v{version:apiVersion}/auth")]
|
||||
public sealed class AuthController(IMiniAuthService authService) : BaseApiController
|
||||
{
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 微信登录
|
||||
/// </summary>
|
||||
@@ -29,7 +25,10 @@ public sealed class AuthController(IMiniAuthService authService) : BaseApiContro
|
||||
[ProducesResponseType(typeof(ApiResponse<TokenResponse>), StatusCodes.Status200OK)]
|
||||
public async Task<ApiResponse<TokenResponse>> LoginWithWeChat([FromBody] WeChatLoginRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 调用认证服务完成微信登录
|
||||
var response = await authService.LoginWithWeChatAsync(request, cancellationToken);
|
||||
|
||||
// 2. 返回访问与刷新令牌
|
||||
return ApiResponse<TokenResponse>.Ok(response);
|
||||
}
|
||||
|
||||
@@ -41,7 +40,10 @@ public sealed class AuthController(IMiniAuthService authService) : BaseApiContro
|
||||
[ProducesResponseType(typeof(ApiResponse<TokenResponse>), StatusCodes.Status200OK)]
|
||||
public async Task<ApiResponse<TokenResponse>> RefreshToken([FromBody] RefreshTokenRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 调用认证服务刷新 Token
|
||||
var response = await authService.RefreshTokenAsync(request, cancellationToken);
|
||||
|
||||
// 2. 返回新的令牌
|
||||
return ApiResponse<TokenResponse>.Ok(response);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,8 +19,6 @@ namespace TakeoutSaaS.MiniApi.Controllers;
|
||||
[Route("api/mini/v{version:apiVersion}/files")]
|
||||
public sealed class FilesController(IFileStorageService fileStorageService) : BaseApiController
|
||||
{
|
||||
private readonly IFileStorageService _fileStorageService = fileStorageService;
|
||||
|
||||
/// <summary>
|
||||
/// 上传图片或文件。
|
||||
/// </summary>
|
||||
@@ -30,23 +28,28 @@ public sealed class FilesController(IFileStorageService fileStorageService) : Ba
|
||||
[ProducesResponseType(typeof(ApiResponse<FileUploadResponse>), StatusCodes.Status400BadRequest)]
|
||||
public async Task<ApiResponse<FileUploadResponse>> Upload([FromForm] IFormFile? file, [FromForm] string? type, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 校验文件有效性
|
||||
if (file == null || file.Length == 0)
|
||||
{
|
||||
return ApiResponse<FileUploadResponse>.Error(ErrorCodes.BadRequest, "文件不能为空");
|
||||
}
|
||||
|
||||
// 2. 解析上传类型
|
||||
if (!UploadFileTypeParser.TryParse(type, out var uploadType))
|
||||
{
|
||||
return ApiResponse<FileUploadResponse>.Error(ErrorCodes.BadRequest, "上传类型不合法");
|
||||
}
|
||||
|
||||
// 3. 提取请求来源
|
||||
var origin = Request.Headers["Origin"].FirstOrDefault() ?? Request.Headers["Referer"].FirstOrDefault();
|
||||
await using var stream = file.OpenReadStream();
|
||||
|
||||
var result = await _fileStorageService.UploadAsync(
|
||||
// 4. 调用存储服务执行上传
|
||||
var result = await fileStorageService.UploadAsync(
|
||||
new UploadFileRequest(uploadType, stream, file.FileName, file.ContentType ?? string.Empty, file.Length, origin),
|
||||
cancellationToken);
|
||||
|
||||
// 5. 返回上传结果
|
||||
return ApiResponse<FileUploadResponse>.Ok(result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,10 @@ public class HealthController : BaseApiController
|
||||
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status200OK)]
|
||||
public ApiResponse<object> Get()
|
||||
{
|
||||
// 1. 构造健康状态
|
||||
var payload = new { status = "OK", service = "MiniApi", time = DateTime.UtcNow };
|
||||
|
||||
// 2. 返回健康响应
|
||||
return ApiResponse<object>.Ok(payload);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,17 +16,13 @@ namespace TakeoutSaaS.MiniApi.Controllers;
|
||||
/// <summary>
|
||||
/// 当前用户信息
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
///
|
||||
/// </remarks>
|
||||
/// <param name="authService"></param>
|
||||
/// <remarks>提供小程序端当前用户档案查询。</remarks>
|
||||
/// <param name="authService">小程序认证服务</param>
|
||||
[ApiVersion("1.0")]
|
||||
[Authorize]
|
||||
[Route("api/mini/v{version:apiVersion}/me")]
|
||||
public sealed class MeController(IMiniAuthService authService) : BaseApiController
|
||||
{
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取用户档案
|
||||
/// </summary>
|
||||
@@ -35,12 +31,14 @@ public sealed class MeController(IMiniAuthService authService) : BaseApiControll
|
||||
[ProducesResponseType(typeof(ApiResponse<CurrentUserProfile>), StatusCodes.Status401Unauthorized)]
|
||||
public async Task<ApiResponse<CurrentUserProfile>> Get(CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 从 JWT 中解析用户标识
|
||||
var userId = User.GetUserId();
|
||||
if (userId == 0)
|
||||
{
|
||||
return ApiResponse<CurrentUserProfile>.Error(ErrorCodes.Unauthorized, "Token 缺少有效的用户标识");
|
||||
}
|
||||
|
||||
// 2. 查询用户档案并返回
|
||||
var profile = await authService.GetProfileAsync(userId, cancellationToken);
|
||||
return ApiResponse<CurrentUserProfile>.Ok(profile);
|
||||
}
|
||||
|
||||
@@ -18,9 +18,11 @@ using TakeoutSaaS.Shared.Kernel.Ids;
|
||||
using TakeoutSaaS.Shared.Web.Extensions;
|
||||
using TakeoutSaaS.Shared.Web.Swagger;
|
||||
|
||||
// 1. 创建构建器与日志模板
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
const string logTemplate = "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} {Level:u3}] [TraceId:{TraceId}] [SpanId:{SpanId}] [Service:{Service}] {SourceContext} {Message:lj}{NewLine}{Exception}";
|
||||
|
||||
// 2. 注册雪花 ID 生成器与 Serilog
|
||||
builder.Services.AddSingleton<IIdGenerator>(_ => new SnowflakeIdGenerator());
|
||||
builder.Host.UseSerilog((_, _, configuration) =>
|
||||
{
|
||||
@@ -36,6 +38,7 @@ builder.Host.UseSerilog((_, _, configuration) =>
|
||||
outputTemplate: logTemplate);
|
||||
});
|
||||
|
||||
// 3. 注册通用 Web 能力与 Swagger
|
||||
builder.Services.AddSharedWebCore();
|
||||
builder.Services.AddSharedSwagger(options =>
|
||||
{
|
||||
@@ -43,6 +46,8 @@ builder.Services.AddSharedSwagger(options =>
|
||||
options.Description = "小程序 API 文档";
|
||||
options.EnableAuthorization = true;
|
||||
});
|
||||
|
||||
// 4. 注册多租户与业务模块
|
||||
builder.Services.AddTenantResolution(builder.Configuration);
|
||||
builder.Services.AddStorageModule(builder.Configuration);
|
||||
builder.Services.AddStorageApplication();
|
||||
@@ -51,6 +56,8 @@ builder.Services.AddSmsApplication(builder.Configuration);
|
||||
builder.Services.AddMessagingModule(builder.Configuration);
|
||||
builder.Services.AddMessagingApplication();
|
||||
builder.Services.AddHealthChecks();
|
||||
|
||||
// 5. 配置 OpenTelemetry 采集
|
||||
var otelSection = builder.Configuration.GetSection("Otel");
|
||||
var otelEndpoint = otelSection.GetValue<string>("Endpoint");
|
||||
var useConsoleExporter = otelSection.GetValue<bool?>("UseConsoleExporter") ?? builder.Environment.IsDevelopment();
|
||||
@@ -102,6 +109,7 @@ builder.Services.AddOpenTelemetry()
|
||||
}
|
||||
});
|
||||
|
||||
// 6. 配置 CORS
|
||||
var miniOrigins = ResolveCorsOrigins(builder.Configuration, "Cors:Mini");
|
||||
builder.Services.AddCors(options =>
|
||||
{
|
||||
@@ -111,6 +119,7 @@ builder.Services.AddCors(options =>
|
||||
});
|
||||
});
|
||||
|
||||
// 7. 构建应用并配置中间件管道
|
||||
var app = builder.Build();
|
||||
|
||||
app.UseCors("MiniApiCors");
|
||||
@@ -123,6 +132,7 @@ app.MapPrometheusScrapingEndpoint();
|
||||
app.MapControllers();
|
||||
app.Run();
|
||||
|
||||
// 8. 解析配置中的 CORS 域名
|
||||
static string[] ResolveCorsOrigins(IConfiguration configuration, string sectionKey)
|
||||
{
|
||||
var origins = configuration.GetSection(sectionKey).Get<string[]>();
|
||||
@@ -132,6 +142,7 @@ static string[] ResolveCorsOrigins(IConfiguration configuration, string sectionK
|
||||
.ToArray() ?? [];
|
||||
}
|
||||
|
||||
// 9. 构建 CORS 策略
|
||||
static void ConfigureCorsPolicy(CorsPolicyBuilder policy, string[] origins)
|
||||
{
|
||||
if (origins.Length == 0)
|
||||
|
||||
@@ -23,7 +23,10 @@ public class HealthController : BaseApiController
|
||||
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status200OK)]
|
||||
public ApiResponse<object> Get()
|
||||
{
|
||||
// 1. 构造健康状态
|
||||
var payload = new { status = "OK", service = "UserApi", time = DateTime.UtcNow };
|
||||
|
||||
// 2. 返回健康响应
|
||||
return ApiResponse<object>.Ok(payload);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,9 +12,11 @@ using TakeoutSaaS.Shared.Kernel.Ids;
|
||||
using TakeoutSaaS.Shared.Web.Extensions;
|
||||
using TakeoutSaaS.Shared.Web.Swagger;
|
||||
|
||||
// 1. 创建构建器与日志模板
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
const string logTemplate = "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} {Level:u3}] [TraceId:{TraceId}] [SpanId:{SpanId}] [Service:{Service}] {SourceContext} {Message:lj}{NewLine}{Exception}";
|
||||
|
||||
// 2. 注册雪花 ID 生成器与 Serilog
|
||||
builder.Services.AddSingleton<IIdGenerator>(_ => new SnowflakeIdGenerator());
|
||||
builder.Host.UseSerilog((_, _, configuration) =>
|
||||
{
|
||||
@@ -30,6 +32,7 @@ builder.Host.UseSerilog((_, _, configuration) =>
|
||||
outputTemplate: logTemplate);
|
||||
});
|
||||
|
||||
// 3. 注册通用 Web 能力与 Swagger
|
||||
builder.Services.AddSharedWebCore();
|
||||
builder.Services.AddSharedSwagger(options =>
|
||||
{
|
||||
@@ -37,8 +40,12 @@ builder.Services.AddSharedSwagger(options =>
|
||||
options.Description = "C 端用户 API 文档";
|
||||
options.EnableAuthorization = true;
|
||||
});
|
||||
|
||||
// 4. 注册多租户与健康检查
|
||||
builder.Services.AddTenantResolution(builder.Configuration);
|
||||
builder.Services.AddHealthChecks();
|
||||
|
||||
// 5. 配置 OpenTelemetry 采集
|
||||
var otelSection = builder.Configuration.GetSection("Otel");
|
||||
var otelEndpoint = otelSection.GetValue<string>("Endpoint");
|
||||
var useConsoleExporter = otelSection.GetValue<bool?>("UseConsoleExporter") ?? builder.Environment.IsDevelopment();
|
||||
@@ -90,6 +97,7 @@ builder.Services.AddOpenTelemetry()
|
||||
}
|
||||
});
|
||||
|
||||
// 6. 配置 CORS
|
||||
var userOrigins = ResolveCorsOrigins(builder.Configuration, "Cors:User");
|
||||
builder.Services.AddCors(options =>
|
||||
{
|
||||
@@ -99,6 +107,7 @@ builder.Services.AddCors(options =>
|
||||
});
|
||||
});
|
||||
|
||||
// 7. 构建应用并配置中间件管道
|
||||
var app = builder.Build();
|
||||
|
||||
app.UseCors("UserApiCors");
|
||||
@@ -111,6 +120,7 @@ app.MapPrometheusScrapingEndpoint();
|
||||
app.MapControllers();
|
||||
app.Run();
|
||||
|
||||
// 8. 解析配置中的 CORS 域名
|
||||
static string[] ResolveCorsOrigins(IConfiguration configuration, string sectionKey)
|
||||
{
|
||||
var origins = configuration.GetSection(sectionKey).Get<string[]>();
|
||||
@@ -120,6 +130,7 @@ static string[] ResolveCorsOrigins(IConfiguration configuration, string sectionK
|
||||
.ToArray() ?? [];
|
||||
}
|
||||
|
||||
// 9. 构建 CORS 策略
|
||||
static void ConfigureCorsPolicy(CorsPolicyBuilder policy, string[] origins)
|
||||
{
|
||||
if (origins.Length == 0)
|
||||
|
||||
Reference in New Issue
Block a user