|
个人博客-给文章添加上标签
优化计划
- 置顶3个且可滚动或切换
- 推荐改为4个,然后新增历史文章,将推荐的加载更多放入历史文章,按文章发布时间降序排列。
- 标签功能,可以为文章贴上标签
- 推荐点赞功能
本篇文章实现文章标签功能
思路
首先需要新增一个标签类Tag,然后Post文章类和Tag标签类的关系是多对多的关系。也就是一个文章可以有多个标签,一个标签也可以被多个文章使用。
为了实现这个多对多关系,光有Tag表和Post表还不够,还需要一个中间表去维护标签和文章之间的关联关系,就定为PostTag表吧。
代码实现
准备工作
为Post类新增导航属性- public List<Tag> Tags { get; set; }
复制代码 新增Tag类- public class Tag
- {
- /// <summary>
- /// 标签ID
- /// </summary>
- [Key] //主键
- public int Id { get; set; }
- /// <summary>
- /// 标签名称
- /// </summary>
- public string Name { get; set; }
- /// <summary>
- /// 导航属性 - 文章列表
- /// </summary>
- public List<Post>? Posts { get; set; }
- }
复制代码 新增PostTag类- public class PostTag
- {
- /// <summary>
- /// 标签ID
- /// </summary>
- public int TagId { get; set; }
- /// <summary>
- /// 导航属性 - 文章
- /// </summary>
- public Post Post { get; set; }
- /// <summary>
- /// 导航属性 - 标签
- /// </summary>
- public Tag Tag { get; set; }
- }
复制代码 在DbContext数据库上下文中添加新增类- public DbSet<Tag> Tags { get; set; }
- public DbSet<PostTag> PostTags { get; set; }
复制代码 然后是上下文的protected override void OnModelCreating(ModelBuilder modelBuilder)方法中添加- modelBuilder.Entity<Post>()
- .HasMany(e => e.Tags)
- .WithMany(e => e.Posts)
- .UsingEntity<PostTag>();
复制代码 类创建完成后,需要在数据库中新增Tags表和PostTags表,使用Code First模式或者手动创建都行。
控制器
修改之前打包上传文章的控制器,新增List tags- public async Task<ApiResponse<Post>> Upload([FromForm] String Categoryname,[FromForm]String Parent, [FromForm] List<string> tags,IFormFile file,[FromServices] ICategoryService categoryService )
复制代码 服务
在之前的打包上传服务新增标签处理- public async Task<Post> Upload(int CategoryId, List<string> tags,IFormFile file){
- ....之前的代码
- foreach (var tagName in tags)
- {
- var tag = await _myDbContext.Tags.FirstOrDefaultAsync(t => t.Name == tagName);
- if (tag == null)
- {
- tag = new Tag { Name = tagName };
- _myDbContext.Tags.Add(tag);
- }
- var postTag = new PostTag
- {
- Post = post,
- Tag = tag
- };
- _myDbContext.PostTags.Add(postTag);
- }
- await _myDbContext.SaveChangesAsync();
- return post;
- }
复制代码 接口测试
可以看到tags是一个数组类型的参数
数据库也是添加成功了
Razor页面
上述只是简单的在上传文章的时候设置了一下标签,接下来设计一下页面显示
分页查询服务
首先是分页查询服务,可以看到是返回的一个元组,然后PaginationMetadata是分页数据,之前在做推荐博客加载的时候提过一下,之前是没有用到的,然后现在是用到了,所以需要计算一下分页的信息。顺便提一下这个类是大佬的一个Nuget包,然后是提供了ApiResponsePaged类去把元组和数据类结合在一起,在博客的评论中就用到了ApiResponsePaged类来返回数据给前端。但考虑的标签页的设计,就没用这个类,而是直接使用元组,我发现元组用着也不错。- public async Task<(List<PostTag>, PaginationMetadata)> GetAllTagPostAsync(QueryParameters param)
- {
- var postTags = await _myDbContext.PostTags
- .Where(p => p.TagId == param.TagId)
- .Include(p => p.Post)
- .ThenInclude(p => p.Categories)
- .Include(p => p.Post)
- .ThenInclude(p => p.Comments)
- .Include(p => p.Post)
- .ThenInclude(p => p.Tags)
- .Skip((param.Page - 1) * param.PageSize)
- .Take(param.PageSize)
- .ToListAsync();
-
- var totalCount = await _myDbContext.PostTags.CountAsync(p => p.TagId == param.TagId);
- var pageCount = (int)Math.Ceiling((double)totalCount / param.PageSize);
-
- var pagination = new PaginationMetadata()
- {
- PageNumber = param.Page,
- PageSize = param.PageSize,
- TotalItemCount = totalCount,
- PageCount = pageCount,
- HasPreviousPage = param.Page > 1,
- HasNextPage = param.Page < pageCount,
- IsFirstPage = param.Page == 1,
- IsLastPage = param.Page == pageCount,
- FirstItemOnPage = (param.Page - 1) * param.PageSize + 1,
- LastItemOnPage = Math.Min(param.Page * param.PageSize, totalCount)
- };
-
- return (postTags, pagination);
- }
复制代码 控制器
- public async Task<IActionResult> Index(int tagId = 1, int page = 1, int pageSize = 8)
- {
- var TagList = await _tagService.GetAllTagAsync();
- if (TagList.Count == 0)
- return View(new TagIndex()
- {
- TagList = await _tagService.GetAllTagAsync(),
- TagId = 0,
- TagAllPosts = await _tagService.GetAllTagPostAsync(
- new QueryParameters
- {
- Page = page,
- PageSize = pageSize,
- TagId = tagId,
- })
- });
-
- var currentTag = tagId == 1 ? TagList[0] :await _tagService.GetById(tagId);
- if (currentTag == null)
- {
- _messages.Error($"标签 {currentTag} 不存在!");
- return RedirectToAction(nameof(Index));
- }
- TagIndex tagIndex = new TagIndex()
- {
- TagList = await _tagService.GetAllTagAsync(),
- TagId = currentTag.Id,
- TagAllPosts = await _tagService.GetAllTagPostAsync(
- new QueryParameters
- {
- Page = page,
- PageSize = pageSize,
- TagId = currentTag.Id,
- })
- };
- return View(tagIndex);
- }
复制代码 分页组件
[code]@model (Personalblog.Model.ViewModels.Categories.PaginationMetadata,int) <ul > <li disabled" : "")"> « Previous @for (int i = 1; i |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
|