feat: 完成租户个人中心 API 首版实现
This commit is contained in:
245
src/Api/TakeoutSaaS.TenantApi/Controllers/PersonalController.cs
Normal file
245
src/Api/TakeoutSaaS.TenantApi/Controllers/PersonalController.cs
Normal file
@@ -0,0 +1,245 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using MediatR;
|
||||
using TakeoutSaaS.Application.App.Personal.Dto;
|
||||
using TakeoutSaaS.Application.App.Personal.Queries;
|
||||
using TakeoutSaaS.Shared.Abstractions.Results;
|
||||
using TakeoutSaaS.Shared.Web.Api;
|
||||
|
||||
namespace TakeoutSaaS.TenantApi.Controllers;
|
||||
|
||||
/// <summary>
|
||||
/// 租户端个人中心。
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 提供个人总览、角色概览、配额、账单、支付、操作记录与消息摘要能力。
|
||||
/// </remarks>
|
||||
[ApiVersion("1.0")]
|
||||
[Authorize]
|
||||
[Produces("application/json")]
|
||||
[Route("api/tenant/v{version:apiVersion}/personal")]
|
||||
public sealed class PersonalController(IMediator mediator) : BaseApiController
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取个人中心总览。
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">取消标记。</param>
|
||||
/// <returns>总览结果。</returns>
|
||||
[HttpGet("overview")]
|
||||
[ProducesResponseType(typeof(ApiResponse<PersonalOverviewDto>), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(typeof(ApiResponse<PersonalOverviewDto>), StatusCodes.Status401Unauthorized)]
|
||||
public async Task<ApiResponse<PersonalOverviewDto>> GetOverview(CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 查询总览
|
||||
var overview = await mediator.Send(new GetPersonalOverviewQuery(), cancellationToken);
|
||||
|
||||
// 2. 返回结果
|
||||
return ApiResponse<PersonalOverviewDto>.Ok(overview);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取我的角色与权限概览。
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">取消标记。</param>
|
||||
/// <returns>角色权限概览。</returns>
|
||||
[HttpGet("roles")]
|
||||
[ProducesResponseType(typeof(ApiResponse<PersonalRolePermissionSummaryDto>), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(typeof(ApiResponse<PersonalRolePermissionSummaryDto>), StatusCodes.Status401Unauthorized)]
|
||||
public async Task<ApiResponse<PersonalRolePermissionSummaryDto>> GetRoles(CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 查询角色权限概览
|
||||
var summary = await mediator.Send(new GetPersonalRolesQuery(), cancellationToken);
|
||||
|
||||
// 2. 返回结果
|
||||
return ApiResponse<PersonalRolePermissionSummaryDto>.Ok(summary);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取套餐与配额摘要。
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">取消标记。</param>
|
||||
/// <returns>配额摘要。</returns>
|
||||
[HttpGet("quota")]
|
||||
[ProducesResponseType(typeof(ApiResponse<PersonalQuotaUsageSummaryDto>), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(typeof(ApiResponse<PersonalQuotaUsageSummaryDto>), StatusCodes.Status401Unauthorized)]
|
||||
[ProducesResponseType(typeof(ApiResponse<PersonalQuotaUsageSummaryDto>), StatusCodes.Status403Forbidden)]
|
||||
public async Task<ApiResponse<PersonalQuotaUsageSummaryDto>> GetQuota(CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 查询配额摘要
|
||||
var summary = await mediator.Send(new GetPersonalQuotaQuery(), cancellationToken);
|
||||
|
||||
// 2. 返回结果
|
||||
return ApiResponse<PersonalQuotaUsageSummaryDto>.Ok(summary);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 分页查询账单记录。
|
||||
/// </summary>
|
||||
/// <param name="page">页码(从 1 开始)。</param>
|
||||
/// <param name="pageSize">每页条数。</param>
|
||||
/// <param name="from">开始时间(UTC)。</param>
|
||||
/// <param name="to">结束时间(UTC)。</param>
|
||||
/// <param name="cancellationToken">取消标记。</param>
|
||||
/// <returns>账单分页结果。</returns>
|
||||
[HttpGet("billing/statements")]
|
||||
[ProducesResponseType(typeof(ApiResponse<PagedResult<PersonalBillingStatementDto>>), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(typeof(ApiResponse<PagedResult<PersonalBillingStatementDto>>), StatusCodes.Status401Unauthorized)]
|
||||
[ProducesResponseType(typeof(ApiResponse<PagedResult<PersonalBillingStatementDto>>), StatusCodes.Status403Forbidden)]
|
||||
[ProducesResponseType(typeof(ApiResponse<PagedResult<PersonalBillingStatementDto>>), StatusCodes.Status422UnprocessableEntity)]
|
||||
public async Task<ApiResponse<PagedResult<PersonalBillingStatementDto>>> SearchBillingStatements(
|
||||
[FromQuery] int page = 1,
|
||||
[FromQuery] int pageSize = 20,
|
||||
[FromQuery] DateTime? from = null,
|
||||
[FromQuery] DateTime? to = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
// 1. 发送查询
|
||||
var result = await mediator.Send(new SearchPersonalBillingStatementsQuery
|
||||
{
|
||||
Page = page,
|
||||
PageSize = pageSize,
|
||||
From = from,
|
||||
To = to
|
||||
}, cancellationToken);
|
||||
|
||||
// 2. 返回分页结果
|
||||
return ApiResponse<PagedResult<PersonalBillingStatementDto>>.Ok(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 分页查询支付记录。
|
||||
/// </summary>
|
||||
/// <param name="page">页码(从 1 开始)。</param>
|
||||
/// <param name="pageSize">每页条数。</param>
|
||||
/// <param name="from">开始时间(UTC)。</param>
|
||||
/// <param name="to">结束时间(UTC)。</param>
|
||||
/// <param name="cancellationToken">取消标记。</param>
|
||||
/// <returns>支付记录分页结果。</returns>
|
||||
[HttpGet("billing/payments")]
|
||||
[ProducesResponseType(typeof(ApiResponse<PagedResult<PersonalPaymentRecordDto>>), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(typeof(ApiResponse<PagedResult<PersonalPaymentRecordDto>>), StatusCodes.Status401Unauthorized)]
|
||||
[ProducesResponseType(typeof(ApiResponse<PagedResult<PersonalPaymentRecordDto>>), StatusCodes.Status403Forbidden)]
|
||||
[ProducesResponseType(typeof(ApiResponse<PagedResult<PersonalPaymentRecordDto>>), StatusCodes.Status422UnprocessableEntity)]
|
||||
public async Task<ApiResponse<PagedResult<PersonalPaymentRecordDto>>> SearchPayments(
|
||||
[FromQuery] int page = 1,
|
||||
[FromQuery] int pageSize = 20,
|
||||
[FromQuery] DateTime? from = null,
|
||||
[FromQuery] DateTime? to = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
// 1. 发送查询
|
||||
var result = await mediator.Send(new SearchPersonalPaymentsQuery
|
||||
{
|
||||
Page = page,
|
||||
PageSize = pageSize,
|
||||
From = from,
|
||||
To = to
|
||||
}, cancellationToken);
|
||||
|
||||
// 2. 返回分页结果
|
||||
return ApiResponse<PagedResult<PersonalPaymentRecordDto>>.Ok(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取账单/配额可见角色配置。
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">取消标记。</param>
|
||||
/// <returns>可见角色配置。</returns>
|
||||
[HttpGet("visibility/roles")]
|
||||
[ProducesResponseType(typeof(ApiResponse<PersonalVisibilityRoleConfigDto>), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(typeof(ApiResponse<PersonalVisibilityRoleConfigDto>), StatusCodes.Status401Unauthorized)]
|
||||
[ProducesResponseType(typeof(ApiResponse<PersonalVisibilityRoleConfigDto>), StatusCodes.Status403Forbidden)]
|
||||
public async Task<ApiResponse<PersonalVisibilityRoleConfigDto>> GetVisibilityRoles(CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 查询配置
|
||||
var config = await mediator.Send(new GetPersonalVisibilityRoleConfigQuery(), cancellationToken);
|
||||
|
||||
// 2. 返回结果
|
||||
return ApiResponse<PersonalVisibilityRoleConfigDto>.Ok(config);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新账单/配额可见角色配置。
|
||||
/// </summary>
|
||||
/// <param name="command">更新请求。</param>
|
||||
/// <param name="cancellationToken">取消标记。</param>
|
||||
/// <returns>更新后的配置。</returns>
|
||||
[HttpPut("visibility/roles")]
|
||||
[ProducesResponseType(typeof(ApiResponse<PersonalVisibilityRoleConfigDto>), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(typeof(ApiResponse<PersonalVisibilityRoleConfigDto>), StatusCodes.Status401Unauthorized)]
|
||||
[ProducesResponseType(typeof(ApiResponse<PersonalVisibilityRoleConfigDto>), StatusCodes.Status403Forbidden)]
|
||||
[ProducesResponseType(typeof(ApiResponse<PersonalVisibilityRoleConfigDto>), StatusCodes.Status422UnprocessableEntity)]
|
||||
public async Task<ApiResponse<PersonalVisibilityRoleConfigDto>> UpdateVisibilityRoles(
|
||||
[FromBody] UpdatePersonalVisibilityRoleConfigCommand command,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 更新配置
|
||||
var config = await mediator.Send(command, cancellationToken);
|
||||
|
||||
// 2. 返回结果
|
||||
return ApiResponse<PersonalVisibilityRoleConfigDto>.Ok(config);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 分页查询个人操作记录。
|
||||
/// </summary>
|
||||
/// <param name="page">页码(从 1 开始)。</param>
|
||||
/// <param name="pageSize">每页条数(默认 50,最大 50)。</param>
|
||||
/// <param name="from">开始时间(UTC)。</param>
|
||||
/// <param name="to">结束时间(UTC)。</param>
|
||||
/// <param name="cancellationToken">取消标记。</param>
|
||||
/// <returns>操作记录分页结果。</returns>
|
||||
[HttpGet("operations")]
|
||||
[ProducesResponseType(typeof(ApiResponse<PagedResult<PersonalOperationLogDto>>), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(typeof(ApiResponse<PagedResult<PersonalOperationLogDto>>), StatusCodes.Status401Unauthorized)]
|
||||
[ProducesResponseType(typeof(ApiResponse<PagedResult<PersonalOperationLogDto>>), StatusCodes.Status422UnprocessableEntity)]
|
||||
public async Task<ApiResponse<PagedResult<PersonalOperationLogDto>>> SearchOperations(
|
||||
[FromQuery] int page = 1,
|
||||
[FromQuery] int pageSize = 50,
|
||||
[FromQuery] DateTime? from = null,
|
||||
[FromQuery] DateTime? to = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
// 1. 发送查询
|
||||
var result = await mediator.Send(new SearchPersonalOperationsQuery
|
||||
{
|
||||
Page = page,
|
||||
PageSize = pageSize,
|
||||
From = from,
|
||||
To = to
|
||||
}, cancellationToken);
|
||||
|
||||
// 2. 返回分页结果
|
||||
return ApiResponse<PagedResult<PersonalOperationLogDto>>.Ok(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 分页查询个人消息摘要。
|
||||
/// </summary>
|
||||
/// <param name="page">页码(从 1 开始)。</param>
|
||||
/// <param name="pageSize">每页条数。</param>
|
||||
/// <param name="unreadOnly">是否仅返回未读。</param>
|
||||
/// <param name="cancellationToken">取消标记。</param>
|
||||
/// <returns>消息摘要分页结果。</returns>
|
||||
[HttpGet("notifications")]
|
||||
[ProducesResponseType(typeof(ApiResponse<PagedResult<PersonalNotificationDto>>), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(typeof(ApiResponse<PagedResult<PersonalNotificationDto>>), StatusCodes.Status401Unauthorized)]
|
||||
[ProducesResponseType(typeof(ApiResponse<PagedResult<PersonalNotificationDto>>), StatusCodes.Status422UnprocessableEntity)]
|
||||
public async Task<ApiResponse<PagedResult<PersonalNotificationDto>>> SearchNotifications(
|
||||
[FromQuery] int page = 1,
|
||||
[FromQuery] int pageSize = 20,
|
||||
[FromQuery] bool unreadOnly = false,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
// 1. 发送查询
|
||||
var result = await mediator.Send(new SearchPersonalNotificationsQuery
|
||||
{
|
||||
Page = page,
|
||||
PageSize = pageSize,
|
||||
UnreadOnly = unreadOnly
|
||||
}, cancellationToken);
|
||||
|
||||
// 2. 返回分页结果
|
||||
return ApiResponse<PagedResult<PersonalNotificationDto>>.Ok(result);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user