1
This commit is contained in:
71
Yes.Blog/Endpoints/Admins/Articles/CreateArticleEndpoint.cs
Normal file
71
Yes.Blog/Endpoints/Admins/Articles/CreateArticleEndpoint.cs
Normal file
@@ -0,0 +1,71 @@
|
||||
namespace Yes.Blog.Endpoints.Admins.Articles
|
||||
{
|
||||
public class CreateArticleEndpoint : AdminEndpointScheme, IEndpoint
|
||||
{
|
||||
public void Map(IEndpointRouteBuilder app) => app.MapPost("/articles", Handle).WithRequestValidation<Request>();
|
||||
|
||||
public record Request(
|
||||
int CategoryId,
|
||||
string Title,
|
||||
string? Slug,
|
||||
string Content,
|
||||
string? CoverUrl,
|
||||
string? Summary,
|
||||
List<string> Tags,
|
||||
bool IsDraft
|
||||
);
|
||||
|
||||
public class RequestValidator : AbstractValidator<Request>
|
||||
{
|
||||
public RequestValidator()
|
||||
{
|
||||
RuleFor(x => x.Content).NotEmpty().WithMessage("文章内容不能为空!").NotNull().WithMessage("文章内容不能为空!");
|
||||
|
||||
RuleFor(x => x.Title).NotEmpty().WithMessage("标题不能为空!").NotNull().WithMessage("标题不能为空!").When(x => !x.IsDraft);
|
||||
|
||||
RuleFor(x => x.CategoryId).NotEqual(0).WithMessage("请选择分类!").When(x => !x.IsDraft);
|
||||
|
||||
RuleFor(x => x.CoverUrl).MaximumLength(256).WithMessage("封面图地址长度不能超过256!");
|
||||
|
||||
RuleFor(x => x.Tags).ForEach(x => x.MaximumLength(32).WithMessage("单个标签长度不能超过32个字符!"))
|
||||
.Must(y => y.Count() <= 5).WithMessage("标签数量不能超过5个!");
|
||||
|
||||
RuleFor(x => x.Slug).MaximumLength(128).WithMessage("缩略名长度不能超过128!");
|
||||
|
||||
RuleFor(x => x.Slug)
|
||||
.Must(x => x.IsSlug())
|
||||
.WithMessage(x => $"缩略名{x.Slug}无效,只能为字母数字横线和下划线组合,且不能使用纯数字!")
|
||||
.When(x => !string.IsNullOrEmpty(x.Slug));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private async Task<IResult> Handle([FromBody] Request request, IMediator mediator, IMapper mapper, CancellationToken cancellationToken)
|
||||
{
|
||||
var id = 0;
|
||||
if (request.IsDraft)
|
||||
{
|
||||
var command = mapper.Map<CreateDraftCommand>(request);
|
||||
var response = await mediator.Send(command, cancellationToken);
|
||||
}
|
||||
else
|
||||
{
|
||||
var command = mapper.Map<CreateArticleCommand>(request);
|
||||
var response = await mediator.Send(command, cancellationToken);
|
||||
|
||||
|
||||
}
|
||||
|
||||
return Result.Ok(new { Id = id });
|
||||
}
|
||||
}
|
||||
|
||||
internal class CreateArticleMappingProfile : IRegister
|
||||
{
|
||||
public void Register(TypeAdapterConfig config)
|
||||
{
|
||||
config.ForType<CreateArticleEndpoint.Request, CreateArticleCommand>();
|
||||
}
|
||||
}
|
||||
}
|
||||
26
Yes.Blog/Endpoints/Admins/Articles/DeleteArticleEndpoint.cs
Normal file
26
Yes.Blog/Endpoints/Admins/Articles/DeleteArticleEndpoint.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
|
||||
|
||||
|
||||
|
||||
namespace Yes.Blog.Endpoints.Admins.Articles
|
||||
{
|
||||
public class DeleteArticleEndpoint : AdminEndpointScheme, IEndpoint
|
||||
{
|
||||
public void Map(IEndpointRouteBuilder app) => app.MapDelete("/articles", Handle);
|
||||
|
||||
public record Request(int Id);
|
||||
|
||||
|
||||
|
||||
private async Task<IResult> Handle([AsParameters] Request request, IMediator mediator, IMapper mapper, CancellationToken cancellationToken)
|
||||
{
|
||||
var command = new DeleteArticleCommand(request.Id);
|
||||
var response = await mediator.Send(command, cancellationToken);
|
||||
|
||||
|
||||
return Result.Ok(response);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
24
Yes.Blog/Endpoints/Admins/Articles/GetArticleEndpoint.cs
Normal file
24
Yes.Blog/Endpoints/Admins/Articles/GetArticleEndpoint.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
|
||||
|
||||
namespace Yes.Blog.Endpoints.Admins.Articles
|
||||
{
|
||||
public class GetArticleEndpoint : AdminEndpointScheme, IEndpoint
|
||||
{
|
||||
public void Map(IEndpointRouteBuilder app) => app.MapGet("/articles/{id}", Handle);
|
||||
|
||||
public record Request([FromRoute(Name = "id")] int Id);
|
||||
|
||||
|
||||
private async Task<IResult> Handle(
|
||||
[AsParameters] Request request,
|
||||
IMediator mediator,
|
||||
IMapper mapper,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var query = new GetArticleQuery(request.Id);
|
||||
var response = await mediator.Send(query, cancellationToken);
|
||||
|
||||
return Result.Ok(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
24
Yes.Blog/Endpoints/Admins/Articles/GetArticlesEndpoint.cs
Normal file
24
Yes.Blog/Endpoints/Admins/Articles/GetArticlesEndpoint.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
|
||||
|
||||
namespace Yes.Blog.Endpoints.Admins.Articles
|
||||
{
|
||||
public class GetArticlesEndpoint : AdminEndpointScheme, IEndpoint
|
||||
{
|
||||
public void Map(IEndpointRouteBuilder app) => app.MapGet("/articles", Handle);
|
||||
|
||||
public record Request(int? PageIndex);
|
||||
|
||||
|
||||
private async Task<IResult> Handle(
|
||||
[AsParameters] Request request,
|
||||
IMediator mediator,
|
||||
IMapper mapper,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var query = new GetArticlesQuery(request.PageIndex, 15);
|
||||
var response = await mediator.Send(query, cancellationToken);
|
||||
|
||||
return Result.Ok(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
|
||||
|
||||
namespace Yes.Blog.Endpoints.Admins.Articles
|
||||
{
|
||||
public class GetLatestArticlesEndpoint : AdminEndpointScheme, IEndpoint
|
||||
{
|
||||
public void Map(IEndpointRouteBuilder app) => app.MapGet("/articles/Latest", Handle);
|
||||
|
||||
|
||||
|
||||
private async Task<IResult> Handle(
|
||||
IMediator mediator,
|
||||
IMapper mapper,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var query = new GetLatestArticlesQuery();
|
||||
var response = await mediator.Send(query, cancellationToken);
|
||||
|
||||
return Result.Ok(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
71
Yes.Blog/Endpoints/Admins/Articles/UpdateArticleEndpoint.cs
Normal file
71
Yes.Blog/Endpoints/Admins/Articles/UpdateArticleEndpoint.cs
Normal file
@@ -0,0 +1,71 @@
|
||||
namespace Yes.Blog.Endpoints.Admins.Articles
|
||||
{
|
||||
public class UpdateArticleEndpoint : AdminEndpointScheme, IEndpoint
|
||||
{
|
||||
public void Map(IEndpointRouteBuilder app) => app.MapPut("/articles", Handle).WithRequestValidation<Request>();
|
||||
|
||||
public record Request(
|
||||
int Id,
|
||||
int CategoryId,
|
||||
string Title,
|
||||
string? Slug,
|
||||
string Content,
|
||||
string? CoverUrl,
|
||||
string? Summary,
|
||||
List<string> Tags,
|
||||
bool IsDraft
|
||||
);
|
||||
|
||||
public class RequestValidator : AbstractValidator<Request>
|
||||
{
|
||||
public RequestValidator()
|
||||
{
|
||||
RuleFor(x => x.Content).NotEmpty().WithMessage("文章内容不能为空!").NotNull().WithMessage("文章内容不能为空!");
|
||||
|
||||
RuleFor(x => x.Title).NotEmpty().WithMessage("标题不能为空!").NotNull().WithMessage("标题不能为空!").When(x => !x.IsDraft);
|
||||
|
||||
RuleFor(x => x.CategoryId).NotEqual(0).WithMessage("请选择分类!").When(x => !x.IsDraft);
|
||||
|
||||
RuleFor(x => x.CoverUrl).MaximumLength(256).WithMessage("封面图地址长度不能超过256!");
|
||||
|
||||
RuleFor(x => x.Tags).ForEach(x => x.MaximumLength(32).WithMessage("单个标签长度不能超过32个字符!"))
|
||||
.Must(y => y.Count() <= 5).WithMessage("标签数量不能超过5个!");
|
||||
|
||||
RuleFor(x => x.Slug).MaximumLength(128).WithMessage("缩略名长度不能超过128!");
|
||||
|
||||
RuleFor(x => x.Slug)
|
||||
.Must(x => x.IsSlug())
|
||||
.WithMessage(x => $"缩略名{x.Slug}无效,只能为字母数字横线和下划线组合,且不能使用纯数字!")
|
||||
.When(x => !string.IsNullOrEmpty(x.Slug) && x.Id.ToString() != x.Slug);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<IResult> Handle([FromBody] Request request, IMediator mediator, IMapper mapper, CancellationToken cancellationToken)
|
||||
{
|
||||
|
||||
var id = 0;
|
||||
if (request.IsDraft)
|
||||
{
|
||||
var command = mapper.Map<UpdateDraftCommand>(request);
|
||||
var response = await mediator.Send(command, cancellationToken);
|
||||
}
|
||||
else
|
||||
{
|
||||
var command = mapper.Map<UpdateArticleCommand>(request);
|
||||
var response = await mediator.Send(command, cancellationToken);
|
||||
|
||||
}
|
||||
|
||||
|
||||
return Result.Ok(new { Id = id });
|
||||
}
|
||||
}
|
||||
|
||||
internal class UpdateArticleMappingProfile : IRegister
|
||||
{
|
||||
public void Register(TypeAdapterConfig config)
|
||||
{
|
||||
config.ForType<UpdateArticleEndpoint.Request, UpdateArticleCommand>();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user