Răsfoiți Sursa

重构分页代码

懒得勤快 5 ani în urmă
părinte
comite
561e2e49cf
24 a modificat fișierele cu 436 adăugiri și 238 ștergeri
  1. 0 13
      src/Masuit.MyBlogs.Core/Controllers/AdminController.cs
  2. 2 2
      src/Masuit.MyBlogs.Core/Controllers/AdvertisementController.cs
  3. 0 12
      src/Masuit.MyBlogs.Core/Controllers/BaseController.cs
  4. 7 7
      src/Masuit.MyBlogs.Core/Controllers/CommentController.cs
  5. 2 6
      src/Masuit.MyBlogs.Core/Controllers/DonateController.cs
  6. 9 12
      src/Masuit.MyBlogs.Core/Controllers/HomeController.cs
  7. 2 2
      src/Masuit.MyBlogs.Core/Controllers/MergeController.cs
  8. 5 22
      src/Masuit.MyBlogs.Core/Controllers/MiscController.cs
  9. 8 10
      src/Masuit.MyBlogs.Core/Controllers/MsgController.cs
  10. 5 7
      src/Masuit.MyBlogs.Core/Controllers/NoticeController.cs
  11. 6 11
      src/Masuit.MyBlogs.Core/Controllers/PostController.cs
  12. 3 6
      src/Masuit.MyBlogs.Core/Controllers/SearchController.cs
  13. 3 5
      src/Masuit.MyBlogs.Core/Controllers/SeminarController.cs
  14. 2 4
      src/Masuit.MyBlogs.Core/Controllers/SubscribeController.cs
  15. 128 37
      src/Masuit.MyBlogs.Core/Infrastructure/Repository/BaseRepository.cs
  16. 30 7
      src/Masuit.MyBlogs.Core/Infrastructure/Repository/Interface/IBaseRepository.cs
  17. 94 17
      src/Masuit.MyBlogs.Core/Infrastructure/Services/BaseService.cs
  18. 62 11
      src/Masuit.MyBlogs.Core/Infrastructure/Services/Interface/IBaseService.cs
  19. 20 0
      src/Masuit.MyBlogs.Core/Models/DTO/DonateDto.cs
  20. 40 0
      src/Masuit.MyBlogs.Core/Models/DTO/DonateDtoBase.cs
  21. 3 1
      src/Masuit.MyBlogs.Core/Models/Pagination.cs
  22. 0 38
      src/Masuit.MyBlogs.Core/Models/ViewModel/PageDataModel.cs
  23. 4 6
      src/Masuit.MyBlogs.Core/Views/Post/History.cshtml
  24. 1 2
      src/Masuit.MyBlogs.Core/Views/Shared/_Pagination.cshtml

+ 0 - 13
src/Masuit.MyBlogs.Core/Controllers/AdminController.cs

@@ -1,5 +1,4 @@
 using AutoMapper;
-using Masuit.MyBlogs.Core.Common;
 using Masuit.MyBlogs.Core.Configs;
 using Masuit.MyBlogs.Core.Extensions;
 using Masuit.MyBlogs.Core.Infrastructure.Services.Interface;
@@ -47,18 +46,6 @@ namespace Masuit.MyBlogs.Core.Controllers
             });
         }
 
-        /// <summary>
-        /// 分页响应结果
-        /// </summary>
-        /// <param name="data">数据</param>
-        /// <param name="pageCount">总页数</param>
-        /// <param name="total">总条数</param>
-        /// <returns></returns>
-        public ActionResult PageResult(object data, int pageCount, int total)
-        {
-            return Ok(new PageDataModel(data, pageCount, total));
-        }
-
         /// <summary>在调用操作方法前调用。</summary>
         /// <param name="filterContext">有关当前请求和操作的信息。</param>
         public override void OnActionExecuting(ActionExecutingContext filterContext)

+ 2 - 2
src/Masuit.MyBlogs.Core/Controllers/AdvertisementController.cs

@@ -10,6 +10,7 @@ using Masuit.MyBlogs.Core.Models.Enum;
 using Masuit.MyBlogs.Core.Models.ViewModel;
 using Masuit.Tools;
 using Masuit.Tools.Core.Net;
+using Masuit.Tools.Models;
 using Microsoft.AspNetCore.Mvc;
 using Microsoft.EntityFrameworkCore.Internal;
 using System;
@@ -67,8 +68,7 @@ namespace Masuit.MyBlogs.Core.Controllers
                 ad.CategoryNames = ad.CategoryIds.Split(",").Select(c => dic[c]).Join(",");
             }
 
-            var pageCount = Math.Ceiling(total * 1.0 / size).ToInt32();
-            return PageResult(list, pageCount, total);
+            return Ok(new PagedList<AdvertisementViewModel>(list, page, size, total));
         }
 
         /// <summary>

+ 0 - 12
src/Masuit.MyBlogs.Core/Controllers/BaseController.cs

@@ -76,18 +76,6 @@ namespace Masuit.MyBlogs.Core.Controllers
             });
         }
 
-        /// <summary>
-        /// 分页响应数据
-        /// </summary>
-        /// <param name="data">数据</param>
-        /// <param name="pageCount">总页数</param>
-        /// <param name="total">总条数</param>
-        /// <returns></returns>
-        public ActionResult PageResult(object data, int pageCount, int total)
-        {
-            return Ok(new PageDataModel(data, pageCount, total));
-        }
-
         /// <summary>在调用操作方法前调用。</summary>
         /// <param name="filterContext">有关当前请求和操作的信息。</param>
         public override void OnActionExecuting(ActionExecutingContext filterContext)

+ 7 - 7
src/Masuit.MyBlogs.Core/Controllers/CommentController.cs

@@ -197,12 +197,13 @@ namespace Masuit.MyBlogs.Core.Controllers
                     });
                 }
             }
-            var parent = CommentService.GetPagesFromCache(page, size, out total, c => c.PostId == id && c.ParentId == 0 && (c.Status == Status.Pended || CurrentUser.IsAdmin), c => c.CommentDate, false).ToList();
-            if (!parent.Any())
+            var parent = CommentService.GetPagesFromCache(page, size, c => c.PostId == id && c.ParentId == 0 && (c.Status == Status.Pended || CurrentUser.IsAdmin), c => c.CommentDate, false);
+            if (!parent.Data.Any())
             {
                 return ResultData(null, false, "没有评论");
             }
-            parent = parent.SelectMany(c => CommentService.GetSelfAndAllChildrenCommentsByParentId(c.Id).Where(x => (x.Status == Status.Pended || CurrentUser.IsAdmin))).ToList();
+            total = parent.TotalCount;
+            var result = parent.Data.SelectMany(c => CommentService.GetSelfAndAllChildrenCommentsByParentId(c.Id).Where(x => (x.Status == Status.Pended || CurrentUser.IsAdmin))).ToList();
             if (total > 0)
             {
                 return ResultData(new
@@ -211,7 +212,7 @@ namespace Masuit.MyBlogs.Core.Controllers
                     parentTotal = total,
                     page,
                     size,
-                    rows = parent.Mapper<IList<CommentViewModel>>()
+                    rows = result.Mapper<IList<CommentViewModel>>()
                 });
             }
             return ResultData(null, false, "没有评论");
@@ -274,9 +275,8 @@ namespace Masuit.MyBlogs.Core.Controllers
         [MyAuthorize]
         public ActionResult GetPendingComments(int page = 1, int size = 10)
         {
-            var list = CommentService.GetPages<DateTime, CommentDto>(page, size, out int total, c => c.Status == Status.Pending, c => c.CommentDate, false).ToList();
-            var pageCount = Math.Ceiling(total * 1.0 / size).ToInt32();
-            return PageResult(list, pageCount, total);
+            var pages = CommentService.GetPages<DateTime, CommentDto>(page, size, c => c.Status == Status.Pending, c => c.CommentDate, false);
+            return Ok(pages);
         }
     }
 }

+ 2 - 6
src/Masuit.MyBlogs.Core/Controllers/DonateController.cs

@@ -1,10 +1,7 @@
 using Masuit.MyBlogs.Core.Extensions;
 using Masuit.MyBlogs.Core.Infrastructure.Services.Interface;
 using Masuit.MyBlogs.Core.Models.Entity;
-using Masuit.Tools;
 using Microsoft.AspNetCore.Mvc;
-using System;
-using System.Linq;
 using System.Threading.Tasks;
 
 namespace Masuit.MyBlogs.Core.Controllers
@@ -27,9 +24,8 @@ namespace Masuit.MyBlogs.Core.Controllers
         /// <returns></returns>
         public ActionResult GetPageData(int page = 1, int size = 10)
         {
-            var list = DonateService.GetPagesFromCache(page, size, out int total, d => true, d => d.DonateTime, false).ToList();
-            var pageCount = Math.Ceiling(total * 1.0 / size).ToInt32();
-            return PageResult(list, pageCount, total);
+            var list = DonateService.GetPagesFromCache(page, size, d => true, d => d.DonateTime, false);
+            return Ok(list);
         }
 
         /// <summary>

+ 9 - 12
src/Masuit.MyBlogs.Core/Controllers/HomeController.cs

@@ -52,7 +52,7 @@ namespace Masuit.MyBlogs.Core.Controllers
         [HttpGet, ResponseCache(Duration = 600, VaryByQueryKeys = new[] { "orderBy" }, VaryByHeader = "Cookie")]
         public ActionResult Index()
         {
-            ViewBag.Total = PostService.Count(p => p.Status == Status.Pended || CurrentUser.IsAdmin);
+            var total = PostService.Count(p => p.Status == Status.Pended || CurrentUser.IsAdmin);
             var banners = AdsService.GetsByWeightedPrice(8, AdvertiseType.Banner).OrderBy(a => Guid.NewGuid()).ToList();
             var fastShares = FastShareService.GetAllFromCache(s => s.Sort).ToList();
             var postsQuery = PostService.GetQuery<PostDto>(p => (p.Status == Status.Pended || CurrentUser.IsAdmin)); //准备文章的查询
@@ -61,7 +61,7 @@ namespace Masuit.MyBlogs.Core.Controllers
             viewModel.Banner = banners;
             viewModel.Posts = Enumerable.AsEnumerable(postsQuery.Where(p => p.IsFixedTop).OrderByDescending(p => p.ModifyDate)).Union(posts).ToList();
             ViewBag.FastShare = fastShares;
-            ViewData["page"] = new Pagination(1, 15, OrderBy.ModifyDate);
+            ViewData["page"] = new Pagination(1, 15, total, OrderBy.ModifyDate);
             return View(viewModel);
         }
 
@@ -75,7 +75,7 @@ namespace Masuit.MyBlogs.Core.Controllers
         [Route("p"), ResponseCache(Duration = 600, VaryByQueryKeys = new[] { "page", "size", "orderBy" }, VaryByHeader = "Cookie")]
         public ActionResult Post([Optional]OrderBy? orderBy, [Range(1, int.MaxValue, ErrorMessage = "页码必须大于0")]int page = 1, [Range(1, int.MaxValue, ErrorMessage = "页大小必须大于0")]int size = 15)
         {
-            ViewBag.Total = PostService.Count(p => p.Status == Status.Pended || CurrentUser.IsAdmin && !p.IsFixedTop);
+            var total = PostService.Count(p => p.Status == Status.Pended || CurrentUser.IsAdmin && !p.IsFixedTop);
             var viewModel = GetIndexPageViewModel();
             var postsQuery = PostService.GetQuery<PostDto>(p => (p.Status == Status.Pended || CurrentUser.IsAdmin)); //准备文章的查询
             var posts = postsQuery.Where(p => !p.IsFixedTop).OrderBy((orderBy ?? OrderBy.ModifyDate).GetDisplay() + " desc").Skip(size * (page - 1)).Take(size).Cacheable().ToList();
@@ -85,7 +85,7 @@ namespace Masuit.MyBlogs.Core.Controllers
             }
 
             viewModel.Posts = posts;
-            ViewData["page"] = new Pagination(page, size, orderBy);
+            ViewData["page"] = new Pagination(page, size, total, orderBy);
             return View(viewModel);
         }
 
@@ -103,10 +103,9 @@ namespace Masuit.MyBlogs.Core.Controllers
             var temp = PostService.GetQuery<PostDto>(p => p.Label.Contains(id) && (p.Status == Status.Pended || CurrentUser.IsAdmin));
             var posts = temp.OrderBy($"{nameof(PostDto.IsFixedTop)} desc,{(orderBy ?? OrderBy.ModifyDate).GetDisplay()} desc").Skip(size * (page - 1)).Take(size).Cacheable().ToList();
             var viewModel = GetIndexPageViewModel();
-            ViewBag.Total = temp.Count();
             ViewBag.Tag = id;
             viewModel.Posts = posts;
-            ViewData["page"] = new Pagination(page, size, orderBy);
+            ViewData["page"] = new Pagination(page, size, temp.Count(), orderBy);
             return View(viewModel);
         }
 
@@ -126,10 +125,9 @@ namespace Masuit.MyBlogs.Core.Controllers
             var temp = PostService.GetQuery<PostDto>(where);
             var posts = temp.OrderBy($"{nameof(PostDto.IsFixedTop)} desc,{(orderBy ?? OrderBy.ModifyDate).GetDisplay()} desc").Skip(size * (page - 1)).Take(size).Cacheable().ToList();
             var viewModel = GetIndexPageViewModel();
-            ViewBag.Total = temp.Count();
             ViewBag.Author = author;
             viewModel.Posts = posts;
-            ViewData["page"] = new Pagination(page, size, orderBy);
+            ViewData["page"] = new Pagination(page, size, temp.Count(), orderBy);
             return View(viewModel);
         }
 
@@ -147,11 +145,10 @@ namespace Masuit.MyBlogs.Core.Controllers
         {
             var cat = await CategoryService.GetByIdAsync(id) ?? throw new NotFoundException("文章分类未找到");
             var posts = PostService.GetQuery<PostDto>(p => p.CategoryId == cat.Id && (p.Status == Status.Pended || CurrentUser.IsAdmin));
-            ViewBag.Total = posts.Count();
             var viewModel = GetIndexPageViewModel();
             viewModel.Posts = posts.OrderBy($"{nameof(PostDto.IsFixedTop)} desc,{(orderBy ?? OrderBy.ModifyDate).GetDisplay()} desc").Skip(size * (page - 1)).Take(size).Cacheable().ToList();
             ViewBag.Category = cat;
-            ViewData["page"] = new Pagination(page, size, orderBy);
+            ViewData["page"] = new Pagination(page, size, posts.Count(), orderBy);
             return View(viewModel);
         }
 
@@ -162,7 +159,7 @@ namespace Masuit.MyBlogs.Core.Controllers
         private HomePageViewModel GetIndexPageViewModel()
         {
             var postsQuery = PostService.GetQuery<PostDto>(p => (p.Status == Status.Pended || CurrentUser.IsAdmin)); //准备文章的查询
-            var notices = NoticeService.GetPagesFromCache<DateTime, NoticeDto>(1, 5, out _, n => (n.Status == Status.Display || CurrentUser.IsAdmin), n => n.ModifyDate, false).ToList(); //加载前5条公告
+            var notices = NoticeService.GetPagesFromCache<DateTime, NoticeDto>(1, 5, n => (n.Status == Status.Display || CurrentUser.IsAdmin), n => n.ModifyDate, false); //加载前5条公告
             var cats = CategoryService.GetQueryFromCache<string, CategoryDto>(c => c.Status == Status.Available, c => c.Name).ToList(); //加载分类目录
             var hotSearches = RedisHelper.Get<List<KeywordsRank>>("SearchRank:Week").Take(10).ToList(); //热词统计
             var hot6Post = postsQuery.OrderBy((new Random().Next() % 3) switch
@@ -188,7 +185,7 @@ namespace Masuit.MyBlogs.Core.Controllers
             {
                 Categories = cats,
                 HotSearch = hotSearches,
-                Notices = notices,
+                Notices = notices.Data,
                 Tags = newdic,
                 Top6Post = hot6Post,
                 PostsQueryable = postsQuery,

+ 2 - 2
src/Masuit.MyBlogs.Core/Controllers/MergeController.cs

@@ -10,6 +10,7 @@ using Masuit.MyBlogs.Core.Models.DTO;
 using Masuit.MyBlogs.Core.Models.Entity;
 using Masuit.MyBlogs.Core.Models.Enum;
 using Masuit.Tools;
+using Masuit.Tools.Models;
 using Microsoft.AspNetCore.Hosting;
 using Microsoft.AspNetCore.Mvc;
 using System;
@@ -55,8 +56,7 @@ namespace Masuit.MyBlogs.Core.Controllers
 
             var list = PostMergeRequestService.GetQuery(where).OrderByDescending(d => d.MergeState == MergeStatus.Pending).ThenByDescending(r => r.Id).Skip((page - 1) * size).Take(size).ProjectTo<PostMergeRequestDtoBase>(MapperConfig).ToList();
             var count = PostMergeRequestService.Count(where);
-            var pageCount = Math.Ceiling(count * 1.0 / size).ToInt32();
-            return PageResult(list, pageCount, count);
+            return Ok(new PagedList<PostMergeRequestDtoBase>(list, page, size, count));
         }
 
         /// <summary>

+ 5 - 22
src/Masuit.MyBlogs.Core/Controllers/MiscController.cs

@@ -1,5 +1,4 @@
-using EFSecondLevelCache.Core;
-using Masuit.MyBlogs.Core.Common;
+using Masuit.MyBlogs.Core.Common;
 using Masuit.MyBlogs.Core.Extensions;
 using Masuit.MyBlogs.Core.Infrastructure.Services.Interface;
 using Masuit.MyBlogs.Core.Models.DTO;
@@ -64,17 +63,8 @@ namespace Masuit.MyBlogs.Core.Controllers
         [Route("donatelist")]
         public ActionResult DonateList(int page = 1, int size = 10)
         {
-            var list = DonateService.GetPages(page, size, out int total, d => true, d => d.DonateTime, false).Select(d => new
-            {
-                d.NickName,
-                d.EmailDisplay,
-                d.QQorWechatDisplay,
-                d.DonateTime,
-                d.Amount,
-                d.Via
-            }).Cacheable().ToList();
-            var pageCount = Math.Ceiling(total * 1.0 / size).ToInt32();
-            return PageResult(list, pageCount, total);
+            var list = DonateService.GetPagesFromCache<DateTime, DonateDtoBase>(page, size, d => true, d => d.DonateTime, false);
+            return Ok(list);
         }
 
         /// <summary>
@@ -170,15 +160,8 @@ namespace Masuit.MyBlogs.Core.Controllers
         [MyAuthorize]
         public ActionResult GetPageData(int page = 1, int size = 10)
         {
-            var list = MiscService.GetPagesNoTracking(page, size, out int total, n => true, n => n.ModifyDate, false).Select(m => new
-            {
-                m.Id,
-                m.Title,
-                m.ModifyDate,
-                m.PostDate
-            }).ToList();
-            var pageCount = Math.Ceiling(total * 1.0 / size).ToInt32();
-            return PageResult(list, pageCount, total);
+            var list = MiscService.GetPagesFromCache(page, size, n => true, n => n.ModifyDate, false);
+            return Ok(list);
         }
 
         /// <summary>

+ 8 - 10
src/Masuit.MyBlogs.Core/Controllers/MsgController.cs

@@ -77,13 +77,13 @@ namespace Masuit.MyBlogs.Core.Controllers
                     });
                 }
             }
-            var parent = LeaveMessageService.GetPagesNoTracking(page, size, out total, m => m.ParentId == 0 && (m.Status == Status.Pended || CurrentUser.IsAdmin), m => m.PostDate, false);
-            if (!parent.Any())
+            var parent = LeaveMessageService.GetPagesNoTracking(page, size, m => m.ParentId == 0 && (m.Status == Status.Pended || CurrentUser.IsAdmin), m => m.PostDate, false);
+            if (!parent.Data.Any())
             {
                 return ResultData(null, false, "没有留言");
             }
-
-            var qlist = parent.AsEnumerable().SelectMany(c => LeaveMessageService.GetSelfAndAllChildrenMessagesByParentId(c.Id)).Where(c => c.Status == Status.Pended || CurrentUser.IsAdmin);
+            total = parent.TotalCount;
+            var qlist = parent.Data.SelectMany(c => LeaveMessageService.GetSelfAndAllChildrenMessagesByParentId(c.Id)).Where(c => c.Status == Status.Pended || CurrentUser.IsAdmin);
             if (total > 0)
             {
                 return ResultData(new
@@ -233,9 +233,8 @@ namespace Masuit.MyBlogs.Core.Controllers
         [MyAuthorize]
         public ActionResult GetPendingMsgs(int page = 1, int size = 10)
         {
-            var list = LeaveMessageService.GetPages<DateTime, LeaveMessageDto>(page, size, out int total, m => m.Status == Status.Pending, l => l.PostDate, false).ToList();
-            var pageCount = Math.Ceiling(total * 1.0 / size).ToInt32();
-            return PageResult(list, pageCount, total);
+            var list = LeaveMessageService.GetPages<DateTime, LeaveMessageDto>(page, size, m => m.Status == Status.Pending, l => l.PostDate, false);
+            return Ok(list);
         }
 
         #region 站内消息
@@ -289,9 +288,8 @@ namespace Masuit.MyBlogs.Core.Controllers
         [MyAuthorize]
         public ActionResult GetInternalMsgs(int page = 1, int size = 10)
         {
-            var msgs = MessageService.GetPagesNoTracking(page, size, out int total, m => true, m => m.Time, false).ToList();
-            var pageCount = Math.Ceiling(total * 1.0 / size).ToInt32();
-            return PageResult(msgs, pageCount, total);
+            var msgs = MessageService.GetPagesNoTracking(page, size, m => true, m => m.Time, false);
+            return Ok(msgs);
         }
 
         /// <summary>

+ 5 - 7
src/Masuit.MyBlogs.Core/Controllers/NoticeController.cs

@@ -41,10 +41,9 @@ namespace Masuit.MyBlogs.Core.Controllers
         [Route("notice"), ResponseCache(Duration = 600, VaryByQueryKeys = new[] { "page", "size" }, VaryByHeader = "Cookie")]
         public ActionResult Index(int page = 1, int size = 10)
         {
-            var list = NoticeService.GetPages<DateTime, NoticeDto>(page, size, out var total, n => n.Status == Status.Display, n => n.ModifyDate, false).ToList();
-            ViewBag.Total = total;
-            ViewData["page"] = new Pagination(page, size);
-            return CurrentUser.IsAdmin ? View("Index_Admin", list) : View(list);
+            var list = NoticeService.GetPages<DateTime, NoticeDto>(page, size, n => n.Status == Status.Display, n => n.ModifyDate, false);
+            ViewData["page"] = new Pagination(page, size, list.TotalCount);
+            return CurrentUser.IsAdmin ? View("Index_Admin", list.Data) : View(list.Data);
         }
 
         /// <summary>
@@ -128,9 +127,8 @@ namespace Masuit.MyBlogs.Core.Controllers
         /// <returns></returns>
         public ActionResult GetPageData(int page = 1, int size = 10)
         {
-            var list = NoticeService.GetPagesNoTracking(page, size, out int total, n => true, n => n.ModifyDate, false).ToList();
-            var pageCount = Math.Ceiling(total * 1.0 / size).ToInt32();
-            return PageResult(list, pageCount, total);
+            var list = NoticeService.GetPagesNoTracking(page, size, n => true, n => n.ModifyDate, false);
+            return Ok(list);
         }
 
         /// <summary>

+ 6 - 11
src/Masuit.MyBlogs.Core/Controllers/PostController.cs

@@ -9,8 +9,8 @@ using Masuit.MyBlogs.Core.Configs;
 using Masuit.MyBlogs.Core.Extensions;
 using Masuit.MyBlogs.Core.Extensions.Hangfire;
 using Masuit.MyBlogs.Core.Infrastructure;
+using Masuit.MyBlogs.Core.Infrastructure.Repository;
 using Masuit.MyBlogs.Core.Infrastructure.Services.Interface;
-using Masuit.MyBlogs.Core.Models;
 using Masuit.MyBlogs.Core.Models.Command;
 using Masuit.MyBlogs.Core.Models.DTO;
 using Masuit.MyBlogs.Core.Models.Entity;
@@ -20,6 +20,7 @@ using Masuit.Tools;
 using Masuit.Tools.Core.Net;
 using Masuit.Tools.DateTimeExt;
 using Masuit.Tools.Html;
+using Masuit.Tools.Models;
 using Masuit.Tools.Security;
 using Masuit.Tools.Systems;
 using Microsoft.AspNetCore.Hosting;
@@ -101,11 +102,8 @@ namespace Masuit.MyBlogs.Core.Controllers
         {
             var post = await PostService.GetAsync(p => p.Id == id && (p.Status == Status.Pended || CurrentUser.IsAdmin)) ?? throw new NotFoundException("文章未找到");
             ViewBag.Primary = post;
-            var list = PostHistoryVersionService.GetPages(page, size, out int total, v => v.PostId == id, v => v.ModifyDate, false).ToList();
-            ViewBag.Total = total;
-            ViewBag.PageCount = Math.Ceiling(total * 1.0 / size).ToInt32();
+            var list = PostHistoryVersionService.GetPages(page, size, v => v.PostId == id, v => v.ModifyDate, false);
             ViewBag.Ads = AdsService.GetByWeightedPrice(AdvertiseType.InPage, post.CategoryId);
-            ViewData["page"] = new Pagination(page, size);
             return View(list);
         }
 
@@ -621,8 +619,7 @@ namespace Masuit.MyBlogs.Core.Controllers
             var query = PostService.GetQuery(where);
             var total = query.Count();
             var list = query.OrderBy($"{nameof(Post.Status)} desc,{nameof(Post.IsFixedTop)} desc,{orderby.GetDisplay()} desc").Skip((page - 1) * size).Take(size).ProjectTo<PostDataModel>(MapperConfig).ToList();
-            var pageCount = Math.Ceiling(total * 1.0 / size).ToInt32();
-            return PageResult(list, pageCount, total);
+            return Ok(new PagedList<PostDataModel>(list, page, size, total));
         }
 
         /// <summary>
@@ -641,10 +638,8 @@ namespace Masuit.MyBlogs.Core.Controllers
                 where = where.And(p => p.Title.Contains(search) || p.Author.Contains(search) || p.Email.Contains(search) || p.Label.Contains(search));
             }
 
-            var temp = PostService.GetPagesNoTracking(page, size, out var total, where, p => p.Id);
-            var list = temp.OrderByDescending(p => p.IsFixedTop).ThenByDescending(p => p.ModifyDate).ProjectTo<PostDataModel>(MapperConfig).ToList();
-            var pageCount = Math.Ceiling(total * 1.0 / size).ToInt32();
-            return PageResult(list, pageCount, total);
+            var pages = PostService.GetQuery(where).OrderByDescending(p => p.IsFixedTop).ThenByDescending(p => p.ModifyDate).ToPagedList<Post, PostDataModel>(page, size, MapperConfig);
+            return Ok(pages);
         }
 
         /// <summary>

+ 3 - 6
src/Masuit.MyBlogs.Core/Controllers/SearchController.cs

@@ -41,7 +41,6 @@ namespace Masuit.MyBlogs.Core.Controllers
         {
             var nul = new List<PostDto>();
             ViewBag.Elapsed = 0;
-            ViewBag.Total = 0;
             ViewBag.PageSize = size;
             ViewBag.Keyword = wd;
             string ip = ClientIP;
@@ -71,7 +70,6 @@ namespace Masuit.MyBlogs.Core.Controllers
 
                 var posts = PostService.SearchPage(page, size, wd);
                 ViewBag.Elapsed = posts.Elapsed;
-                ViewBag.Total = posts.Total;
                 if (posts.Total > 1)
                 {
                     CacheManager.AddOrUpdate(key, wd, s => wd);
@@ -84,7 +82,7 @@ namespace Masuit.MyBlogs.Core.Controllers
             }
 
             ViewBag.hotSearches = RedisHelper.Get<List<KeywordsRank>>("SearchRank:Week").Take(10).ToList();
-            ViewData["page"] = new Pagination(page, size);
+            ViewData["page"] = new Pagination(page, size, 0);
             return View(nul);
         }
 
@@ -99,9 +97,8 @@ namespace Masuit.MyBlogs.Core.Controllers
         public ActionResult SearchList(int page = 1, int size = 10, string search = "")
         {
             var where = string.IsNullOrEmpty(search) ? (Expression<Func<SearchDetails, bool>>)(s => true) : s => s.Keywords.Contains(search);
-            var list = SearchDetailsService.GetPages<DateTime, SearchDetailsDto>(page, size, out int total, where, s => s.SearchTime, false).ToList();
-            var pageCount = Math.Ceiling(total * 1.0 / size).ToInt32();
-            return PageResult(list, pageCount, total);
+            var pages = SearchDetailsService.GetPages<DateTime, SearchDetailsDto>(page, size, where, s => s.SearchTime, false);
+            return Ok(pages);
         }
 
         /// <summary>

+ 3 - 5
src/Masuit.MyBlogs.Core/Controllers/SeminarController.cs

@@ -47,12 +47,11 @@ namespace Masuit.MyBlogs.Core.Controllers
             var s = SeminarService.GetById(id) ?? throw new NotFoundException("文章未找到");
             var temp = PostService.GetQuery<PostDto>(p => p.Seminar.Any(x => x.SeminarId == id) && (p.Status == Status.Pended || CurrentUser.IsAdmin));
             var posts = temp.OrderBy($"{nameof(Post.IsFixedTop)} desc,{(orderBy ?? OrderBy.ModifyDate).GetDisplay()} desc").Skip(size * (page - 1)).Take(size).ToList();
-            ViewBag.Total = temp.Count();
             ViewBag.Title = s.Title;
             ViewBag.Desc = s.Description;
             ViewBag.SubTitle = s.SubTitle;
             ViewBag.Ads = AdsService.GetByWeightedPrice(AdvertiseType.PostList);
-            ViewData["page"] = new Pagination(page, size, orderBy);
+            ViewData["page"] = new Pagination(page, size, temp.Count(), orderBy);
             return View(posts);
         }
 
@@ -135,9 +134,8 @@ namespace Masuit.MyBlogs.Core.Controllers
         [MyAuthorize]
         public ActionResult GetPageData(int page, int size)
         {
-            var list = SeminarService.GetPages<int, SeminarDto>(page, size, out int total, s => true, s => s.Id, false).ToList();
-            var pageCount = Math.Ceiling(total * 1.0 / size).ToInt32();
-            return PageResult(list, pageCount, total);
+            var list = SeminarService.GetPages<int, SeminarDto>(page, size, s => true, s => s.Id, false);
+            return Ok(list);
         }
 
         /// <summary>

+ 2 - 4
src/Masuit.MyBlogs.Core/Controllers/SubscribeController.cs

@@ -7,7 +7,6 @@ using Masuit.MyBlogs.Core.Extensions;
 using Masuit.MyBlogs.Core.Infrastructure.Services.Interface;
 using Masuit.MyBlogs.Core.Models.Entity;
 using Masuit.MyBlogs.Core.Models.Enum;
-using Masuit.MyBlogs.Core.Models.ViewModel;
 using Masuit.Tools;
 using Masuit.Tools.DateTimeExt;
 using Masuit.Tools.Logging;
@@ -461,9 +460,8 @@ namespace Masuit.MyBlogs.Core.Controllers
                 where = where.And(b => b.Email.Contains(search));
             }
 
-            var list = BroadcastService.GetPagesFromCache(page, size, out var total, @where, b => b.UpdateTime, false).ToList();
-            var pageCount = Math.Ceiling(total * 1.0 / size).ToInt32();
-            return Ok(new PageDataModel(list, pageCount, total));
+            var list = BroadcastService.GetPagesFromCache(page, size, @where, b => b.UpdateTime, false);
+            return Ok(list);
         }
 
         #endregion

+ 128 - 37
src/Masuit.MyBlogs.Core/Infrastructure/Repository/BaseRepository.cs

@@ -3,6 +3,8 @@ using AutoMapper.QueryableExtensions;
 using EFSecondLevelCache.Core;
 using Masuit.MyBlogs.Core.Infrastructure.Repository.Interface;
 using Masuit.Tools;
+using Masuit.Tools.Core.AspNetCore;
+using Masuit.Tools.Models;
 using Masuit.Tools.Systems;
 using Microsoft.EntityFrameworkCore;
 using System;
@@ -438,26 +440,14 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Repository
         /// <typeparam name="TS"></typeparam>
         /// <param name="pageIndex">第几页</param>
         /// <param name="pageSize">每页大小</param>
-        /// <param name="totalCount">数据总数</param>
         /// <param name="where">where Lambda条件表达式</param>
         /// <param name="orderby">orderby Lambda条件表达式</param>
         /// <param name="isAsc">升序降序</param>
         /// <returns>还未执行的SQL语句</returns>
-        public virtual IQueryable<T> GetPages<TS>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> where, Expression<Func<T, TS>> orderby, bool isAsc)
+        public virtual PagedList<T> GetPages<TS>(int pageIndex, int pageSize, Expression<Func<T, bool>> where, Expression<Func<T, TS>> orderby, bool isAsc)
         {
             var temp = DataContext.Set<T>().Where(where);
-            totalCount = temp.Count();
-            if (pageIndex * pageSize > totalCount)
-            {
-                pageIndex = (int)Math.Ceiling(totalCount / (pageSize * 1.0));
-            }
-
-            if (pageIndex <= 0)
-            {
-                pageIndex = 1;
-            }
-
-            return isAsc ? temp.OrderBy(orderby).Skip(pageSize * (pageIndex - 1)).Take(pageSize) : temp.OrderByDescending(orderby).Skip(pageSize * (pageIndex - 1)).Take(pageSize);
+            return isAsc ? temp.OrderBy(orderby).ToPagedList(pageIndex, pageSize) : temp.OrderByDescending(orderby).ToPagedList(pageIndex, pageSize);
         }
 
         /// <summary>
@@ -466,14 +456,14 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Repository
         /// <typeparam name="TS"></typeparam>
         /// <param name="pageIndex">第几页</param>
         /// <param name="pageSize">每页大小</param>
-        /// <param name="totalCount">数据总数</param>
         /// <param name="where">where Lambda条件表达式</param>
         /// <param name="orderby">orderby Lambda条件表达式</param>
         /// <param name="isAsc">升序降序</param>
         /// <returns>还未执行的SQL语句</returns>
-        public virtual EFCachedQueryable<T> GetPagesFromCache<TS>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc)
+        public virtual PagedList<T> GetPagesFromCache<TS>(int pageIndex, int pageSize, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc)
         {
-            return GetPages(pageIndex, pageSize, out totalCount, where, orderby, isAsc).Cacheable();
+            var temp = DataContext.Set<T>().Where(where);
+            return isAsc ? temp.OrderBy(orderby).ToCachedPagedList(pageIndex, pageSize) : temp.OrderByDescending(orderby).ToCachedPagedList(pageIndex, pageSize);
         }
 
         /// <summary>
@@ -482,26 +472,14 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Repository
         /// <typeparam name="TS"></typeparam>
         /// <param name="pageIndex">第几页</param>
         /// <param name="pageSize">每页大小</param>
-        /// <param name="totalCount">数据总数</param>
         /// <param name="where">where Lambda条件表达式</param>
         /// <param name="orderby">orderby Lambda条件表达式</param>
         /// <param name="isAsc">升序降序</param>
         /// <returns>还未执行的SQL语句</returns>
-        public virtual IQueryable<T> GetPagesNoTracking<TS>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        public virtual PagedList<T> GetPagesNoTracking<TS>(int pageIndex, int pageSize, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
         {
             var temp = DataContext.Set<T>().Where(where).AsNoTracking();
-            totalCount = temp.Count();
-            if (pageIndex * pageSize > totalCount)
-            {
-                pageIndex = (int)Math.Ceiling(totalCount / (pageSize * 1.0));
-            }
-
-            if (pageIndex <= 0)
-            {
-                pageIndex = 1;
-            }
-
-            return isAsc ? temp.OrderBy(orderby).Skip(pageSize * (pageIndex - 1)).Take(pageSize) : temp.OrderByDescending(orderby).Skip(pageSize * (pageIndex - 1)).Take(pageSize);
+            return isAsc ? temp.OrderBy(orderby).ToPagedList(pageIndex, pageSize) : temp.OrderByDescending(orderby).ToPagedList(pageIndex, pageSize);
         }
 
         /// <summary>
@@ -511,14 +489,14 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Repository
         /// <typeparam name="TDto"></typeparam>
         /// <param name="pageIndex">第几页</param>
         /// <param name="pageSize">每页大小</param>
-        /// <param name="totalCount">数据总数</param>
         /// <param name="where">where Lambda条件表达式</param>
         /// <param name="orderby">orderby Lambda条件表达式</param>
         /// <param name="isAsc">升序降序</param>
         /// <returns>还未执行的SQL语句</returns>
-        public virtual IQueryable<TDto> GetPages<TS, TDto>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true) where TDto : class
+        public virtual PagedList<TDto> GetPages<TS, TDto>(int pageIndex, int pageSize, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true) where TDto : class
         {
-            return GetPagesNoTracking(pageIndex, pageSize, out totalCount, where, orderby, isAsc).ProjectTo<TDto>(MapperConfig);
+            var temp = DataContext.Set<T>().Where(where).AsNoTracking();
+            return isAsc ? temp.OrderBy(orderby).ToPagedList<T, TDto>(pageIndex, pageSize, MapperConfig) : temp.OrderByDescending(orderby).ToPagedList<T, TDto>(pageIndex, pageSize, MapperConfig);
         }
 
         /// <summary>
@@ -528,14 +506,14 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Repository
         /// <typeparam name="TDto"></typeparam>
         /// <param name="pageIndex">第几页</param>
         /// <param name="pageSize">每页大小</param>
-        /// <param name="totalCount">数据总数</param>
         /// <param name="where">where Lambda条件表达式</param>
         /// <param name="orderby">orderby Lambda条件表达式</param>
         /// <param name="isAsc">升序降序</param>
         /// <returns>还未执行的SQL语句</returns>
-        public virtual EFCachedQueryable<TDto> GetPagesFromCache<TS, TDto>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true) where TDto : class
+        public virtual PagedList<TDto> GetPagesFromCache<TS, TDto>(int pageIndex, int pageSize, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true) where TDto : class
         {
-            return GetPagesNoTracking(pageIndex, pageSize, out totalCount, where, orderby, isAsc).ProjectTo<TDto>(MapperConfig).Cacheable();
+            var temp = DataContext.Set<T>().Where(where).AsNoTracking();
+            return isAsc ? temp.OrderBy(orderby).ToCachedPagedList<T, TDto>(pageIndex, pageSize, MapperConfig) : temp.OrderByDescending(orderby).ToCachedPagedList<T, TDto>(pageIndex, pageSize, MapperConfig);
         }
 
         /// <summary>
@@ -600,6 +578,40 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Repository
         /// <returns>添加成功</returns>
         public abstract T AddEntity(T t);
 
+        /// <summary>
+        /// 添加或更新实体
+        /// </summary>
+        /// <param name="key">更新键规则</param>
+        /// <param name="t">需要保存的实体</param>
+        /// <returns>保存成功</returns>
+        public T AddOrUpdate<TKey>(Expression<Func<T, TKey>> key, T t)
+        {
+            DataContext.Set<T>().AddOrUpdate(key, t);
+            return t;
+        }
+
+        /// <summary>
+        /// 添加或更新实体
+        /// </summary>
+        /// <param name="key">更新键规则</param>
+        /// <param name="entities">需要保存的实体</param>
+        /// <returns>保存成功</returns>
+        public void AddOrUpdate<TKey>(Expression<Func<T, TKey>> key, params T[] entities)
+        {
+            DataContext.Set<T>().AddOrUpdate(key, entities);
+        }
+
+        /// <summary>
+        /// 添加或更新实体
+        /// </summary>
+        /// <param name="key">更新键规则</param>
+        /// <param name="entities">需要保存的实体</param>
+        /// <returns>保存成功</returns>
+        public void AddOrUpdate<TKey>(Expression<Func<T, TKey>> key, IEnumerable<T> entities)
+        {
+            DataContext.Set<T>().AddOrUpdate(key, entities);
+        }
+
         /// <summary>
         /// 统一保存数据
         /// </summary>
@@ -671,4 +683,83 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Repository
             DataContext = null;
         }
     }
+
+    public static class IQueryableExt
+    {
+        /// <summary>
+        /// 生成分页集合
+        /// </summary>
+        /// <typeparam name="T"></typeparam>
+        /// <param name="query"></param>
+        /// <param name="page">当前页</param>
+        /// <param name="size">页大小</param>
+        /// <returns></returns>
+        public static PagedList<T> ToCachedPagedList<T>(this IOrderedQueryable<T> query, int page, int size)
+        {
+            var totalCount = query.Count();
+            if (page * size > totalCount)
+            {
+                page = (int)Math.Ceiling(totalCount / (size * 1.0));
+            }
+
+            if (page <= 0)
+            {
+                page = 1;
+            }
+
+            var list = query.Skip(size * (page - 1)).Take(size).Cacheable().ToList();
+            return new PagedList<T>(list, page, size, totalCount);
+        }
+
+        /// <summary>
+        /// 生成分页集合
+        /// </summary>
+        /// <typeparam name="T"></typeparam>
+        /// <typeparam name="TDto"></typeparam>
+        /// <param name="query"></param>
+        /// <param name="page">当前页</param>
+        /// <param name="size">页大小</param>
+        /// <returns></returns>
+        public static PagedList<TDto> ToPagedList<T, TDto>(this IOrderedQueryable<T> query, int page, int size, MapperConfiguration mapper)
+        {
+            var totalCount = query.Count();
+            if (page * size > totalCount)
+            {
+                page = (int)Math.Ceiling(totalCount / (size * 1.0));
+            }
+
+            if (page <= 0)
+            {
+                page = 1;
+            }
+
+            var list = query.Skip(size * (page - 1)).Take(size).ProjectTo<TDto>(mapper).ToList();
+            return new PagedList<TDto>(list, page, size, totalCount);
+        }
+        /// <summary>
+        /// 生成分页集合
+        /// </summary>
+        /// <typeparam name="T"></typeparam>
+        /// <typeparam name="TDto"></typeparam>
+        /// <param name="query"></param>
+        /// <param name="page">当前页</param>
+        /// <param name="size">页大小</param>
+        /// <returns></returns>
+        public static PagedList<TDto> ToCachedPagedList<T, TDto>(this IOrderedQueryable<T> query, int page, int size, MapperConfiguration mapper)
+        {
+            var totalCount = query.Count();
+            if (page * size > totalCount)
+            {
+                page = (int)Math.Ceiling(totalCount / (size * 1.0));
+            }
+
+            if (page <= 0)
+            {
+                page = 1;
+            }
+
+            var list = query.Skip(size * (page - 1)).Take(size).ProjectTo<TDto>(mapper).Cacheable().ToList();
+            return new PagedList<TDto>(list, page, size, totalCount);
+        }
+    }
 }

+ 30 - 7
src/Masuit.MyBlogs.Core/Infrastructure/Repository/Interface/IBaseRepository.cs

@@ -1,5 +1,6 @@
 using EFSecondLevelCache.Core;
 using Masuit.MyBlogs.Core.Models.Entity;
+using Masuit.Tools.Models;
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -318,12 +319,11 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Repository.Interface
         /// <typeparam name="TS"></typeparam>
         /// <param name="pageIndex">第几页</param>
         /// <param name="pageSize">每页大小</param>
-        /// <param name="totalCount">数据总数</param>
         /// <param name="where">where Lambda条件表达式</param>
         /// <param name="orderby">orderby Lambda条件表达式</param>
         /// <param name="isAsc">升序降序</param>
         /// <returns>还未执行的SQL语句</returns>
-        IQueryable<T> GetPages<TS>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> where, Expression<Func<T, TS>> orderby, bool isAsc);
+        PagedList<T> GetPages<TS>(int pageIndex, int pageSize, Expression<Func<T, bool>> where, Expression<Func<T, TS>> orderby, bool isAsc);
 
         /// <summary>
         /// 高效分页查询方法,取出被AutoMapper映射后的数据集合
@@ -332,12 +332,11 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Repository.Interface
         /// <typeparam name="TDto"></typeparam>
         /// <param name="pageIndex">第几页</param>
         /// <param name="pageSize">每页大小</param>
-        /// <param name="totalCount">数据总数</param>
         /// <param name="where">where Lambda条件表达式</param>
         /// <param name="orderby">orderby Lambda条件表达式</param>
         /// <param name="isAsc">升序降序</param>
         /// <returns>还未执行的SQL语句</returns>
-        IQueryable<TDto> GetPages<TS, TDto>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> where, Expression<Func<T, TS>> orderby, bool isAsc) where TDto : class;
+        PagedList<TDto> GetPages<TS, TDto>(int pageIndex, int pageSize, Expression<Func<T, bool>> where, Expression<Func<T, TS>> orderby, bool isAsc) where TDto : class;
 
         /// <summary>
         /// 高效分页查询方法,优先从二级缓存读取
@@ -350,7 +349,7 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Repository.Interface
         /// <param name="orderby">orderby Lambda条件表达式</param>
         /// <param name="isAsc">升序降序</param>
         /// <returns>还未执行的SQL语句</returns>
-        EFCachedQueryable<T> GetPagesFromCache<TS>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc);
+        PagedList<T> GetPagesFromCache<TS>(int pageIndex, int pageSize, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc);
 
         /// <summary>
         /// 高效分页查询方法,优先从二级缓存读取,取出被AutoMapper映射后的数据集合
@@ -364,7 +363,7 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Repository.Interface
         /// <param name="orderby">orderby Lambda条件表达式</param>
         /// <param name="isAsc">升序降序</param>
         /// <returns>还未执行的SQL语句</returns>
-        EFCachedQueryable<TDto> GetPagesFromCache<TS, TDto>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc) where TDto : class;
+        PagedList<TDto> GetPagesFromCache<TS, TDto>(int pageIndex, int pageSize, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc) where TDto : class;
 
         /// <summary>
         /// 高效分页查询方法(不跟踪实体)
@@ -377,7 +376,7 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Repository.Interface
         /// <param name="orderby">orderby Lambda条件表达式</param>
         /// <param name="isAsc">升序降序</param>
         /// <returns>还未执行的SQL语句</returns>
-        IQueryable<T> GetPagesNoTracking<TS>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+        PagedList<T> GetPagesNoTracking<TS>(int pageIndex, int pageSize, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
 
         /// <summary>
         /// 根据ID删除实体
@@ -414,6 +413,30 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Repository.Interface
         /// <returns>添加成功</returns>
         T AddEntity(T t);
 
+        /// <summary>
+        /// 添加或更新实体
+        /// </summary>
+        /// <param name="key">更新键规则</param>
+        /// <param name="t">需要保存的实体</param>
+        /// <returns>保存成功</returns>
+        T AddOrUpdate<TKey>(Expression<Func<T, TKey>> key, T t);
+
+        /// <summary>
+        /// 添加或更新实体
+        /// </summary>
+        /// <param name="key">更新键规则</param>
+        /// <param name="entities">需要保存的实体</param>
+        /// <returns>保存成功</returns>
+        void AddOrUpdate<TKey>(Expression<Func<T, TKey>> key, params T[] entities);
+
+        /// <summary>
+        /// 添加或更新实体
+        /// </summary>
+        /// <param name="key">更新键规则</param>
+        /// <param name="entities">需要保存的实体</param>
+        /// <returns>保存成功</returns>
+        void AddOrUpdate<TKey>(Expression<Func<T, TKey>> key, IEnumerable<T> entities);
+
         /// <summary>
         /// 统一保存数据
         /// </summary>

+ 94 - 17
src/Masuit.MyBlogs.Core/Infrastructure/Services/BaseService.cs

@@ -1,7 +1,7 @@
-using EFSecondLevelCache.Core;
-using Masuit.LuceneEFCore.SearchEngine.Interfaces;
+using Masuit.LuceneEFCore.SearchEngine.Interfaces;
 using Masuit.MyBlogs.Core.Infrastructure.Repository.Interface;
 using Masuit.MyBlogs.Core.Infrastructure.Services.Interface;
+using Masuit.Tools.Models;
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -443,14 +443,13 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Services
         /// <typeparam name="TS"></typeparam>
         /// <param name="pageIndex">第几页</param>
         /// <param name="pageSize">每页大小</param>
-        /// <param name="totalCount">数据总数</param>
         /// <param name="where">where Lambda条件表达式</param>
         /// <param name="orderby">orderby Lambda条件表达式</param>
         /// <param name="isAsc">升序降序</param>
         /// <returns>还未执行的SQL语句</returns>
-        public virtual IQueryable<T> GetPages<TS>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> where, Expression<Func<T, TS>> orderby, bool isAsc = true)
+        public virtual PagedList<T> GetPages<TS>(int pageIndex, int pageSize, Expression<Func<T, bool>> where, Expression<Func<T, TS>> orderby, bool isAsc = true)
         {
-            return BaseDal.GetPages(pageIndex, pageSize, out totalCount, where, orderby, isAsc);
+            return BaseDal.GetPages(pageIndex, pageSize, where, orderby, isAsc);
         }
 
         /// <summary>
@@ -460,14 +459,13 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Services
         /// <typeparam name="TDto">映射实体</typeparam>
         /// <param name="pageIndex">第几页</param>
         /// <param name="pageSize">每页大小</param>
-        /// <param name="totalCount">数据总数</param>
         /// <param name="where">where Lambda条件表达式</param>
         /// <param name="orderby">orderby Lambda条件表达式</param>
         /// <param name="isAsc">升序降序</param>
         /// <returns>还未执行的SQL语句</returns>
-        public virtual IQueryable<TDto> GetPages<TS, TDto>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc) where TDto : class
+        public virtual PagedList<TDto> GetPages<TS, TDto>(int pageIndex, int pageSize, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc) where TDto : class
         {
-            return BaseDal.GetPages<TS, TDto>(pageIndex, pageSize, out totalCount, where, orderby, isAsc);
+            return BaseDal.GetPages<TS, TDto>(pageIndex, pageSize, where, orderby, isAsc);
         }
 
         /// <summary>
@@ -476,14 +474,13 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Services
         /// <typeparam name="TS">排序字段</typeparam>
         /// <param name="pageIndex">第几页</param>
         /// <param name="pageSize">每页大小</param>
-        /// <param name="totalCount">数据总数</param>
         /// <param name="where">where Lambda条件表达式</param>
         /// <param name="orderby">orderby Lambda条件表达式</param>
         /// <param name="isAsc">升序降序</param>
         /// <returns>还未执行的SQL语句</returns>
-        public virtual EFCachedQueryable<T> GetPagesFromCache<TS>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        public virtual PagedList<T> GetPagesFromCache<TS>(int pageIndex, int pageSize, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
         {
-            return BaseDal.GetPagesFromCache(pageIndex, pageSize, out totalCount, where, orderby, isAsc);
+            return BaseDal.GetPagesFromCache(pageIndex, pageSize, where, orderby, isAsc);
         }
 
         /// <summary>
@@ -493,14 +490,13 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Services
         /// <typeparam name="TDto">映射实体</typeparam>
         /// <param name="pageIndex">第几页</param>
         /// <param name="pageSize">每页大小</param>
-        /// <param name="totalCount">数据总数</param>
         /// <param name="where">where Lambda条件表达式</param>
         /// <param name="orderby">orderby Lambda条件表达式</param>
         /// <param name="isAsc">升序降序</param>
         /// <returns>还未执行的SQL语句</returns>
-        public virtual EFCachedQueryable<TDto> GetPagesFromCache<TS, TDto>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc) where TDto : class
+        public virtual PagedList<TDto> GetPagesFromCache<TS, TDto>(int pageIndex, int pageSize, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc) where TDto : class
         {
-            return BaseDal.GetPagesFromCache<TS, TDto>(pageIndex, pageSize, out totalCount, where, orderby, isAsc);
+            return BaseDal.GetPagesFromCache<TS, TDto>(pageIndex, pageSize, where, orderby, isAsc);
         }
 
         /// <summary>
@@ -509,14 +505,13 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Services
         /// <typeparam name="TS">排序字段</typeparam>
         /// <param name="pageIndex">第几页</param>
         /// <param name="pageSize">每页大小</param>
-        /// <param name="totalCount">数据总数</param>
         /// <param name="where">where Lambda条件表达式</param>
         /// <param name="orderby">orderby Lambda条件表达式</param>
         /// <param name="isAsc">升序降序</param>
         /// <returns>还未执行的SQL语句</returns>
-        public virtual IQueryable<T> GetPagesNoTracking<TS>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
+        public virtual PagedList<T> GetPagesNoTracking<TS>(int pageIndex, int pageSize, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true)
         {
-            return BaseDal.GetPagesNoTracking(pageIndex, pageSize, out totalCount, where, orderby, isAsc);
+            return BaseDal.GetPagesNoTracking(pageIndex, pageSize, where, orderby, isAsc);
         }
 
         /// <summary>
@@ -635,6 +630,39 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Services
             return BaseDal.AddEntity(t);
         }
 
+        /// <summary>
+        /// 添加或更新实体
+        /// </summary>
+        /// <param name="key">更新键规则</param>
+        /// <param name="t">需要保存的实体</param>
+        /// <returns>保存成功</returns>
+        public T AddOrUpdate<TKey>(Expression<Func<T, TKey>> key, T t)
+        {
+            return BaseDal.AddOrUpdate(key, t);
+        }
+
+        /// <summary>
+        /// 添加或更新实体
+        /// </summary>
+        /// <param name="key">更新键规则</param>
+        /// <param name="entities">需要保存的实体</param>
+        /// <returns>保存成功</returns>
+        public void AddOrUpdate<TKey>(Expression<Func<T, TKey>> key, params T[] entities)
+        {
+            BaseDal.AddOrUpdate(key, entities);
+        }
+
+        /// <summary>
+        /// 添加或更新实体
+        /// </summary>
+        /// <param name="key">更新键规则</param>
+        /// <param name="entities">需要保存的实体</param>
+        /// <returns>保存成功</returns>
+        public void AddOrUpdate<TKey>(Expression<Func<T, TKey>> key, IEnumerable<T> entities)
+        {
+            BaseDal.AddOrUpdate(key, entities);
+        }
+
         /// <summary>
         /// 添加实体并保存
         /// </summary>
@@ -647,6 +675,55 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Services
             return b ? entity : null;
         }
 
+        /// <summary>
+        /// 添加或更新实体
+        /// </summary>
+        /// <param name="key">更新键规则</param>
+        /// <param name="t">需要保存的实体</param>
+        /// <returns>保存成功</returns>
+        public T AddOrUpdateSaved<TKey>(Expression<Func<T, TKey>> key, T t)
+        {
+            BaseDal.AddOrUpdate(key, t);
+            BaseDal.SaveChanges();
+            return t;
+        }
+
+        /// <summary>
+        /// 添加或更新实体
+        /// </summary>
+        /// <param name="key">更新键规则</param>
+        /// <param name="entities">需要保存的实体</param>
+        /// <returns>保存成功</returns>
+        public void AddOrUpdateSaved<TKey>(Expression<Func<T, TKey>> key, params T[] entities)
+        {
+            AddOrUpdate(key, entities);
+            SaveChanges();
+        }
+
+        /// <summary>
+        /// 添加或更新实体
+        /// </summary>
+        /// <param name="key">更新键规则</param>
+        /// <param name="t">需要保存的实体</param>
+        /// <returns>保存成功</returns>
+        public async Task AddOrUpdateSavedAsync<TKey>(Expression<Func<T, TKey>> key, T t)
+        {
+            AddOrUpdate(key, t);
+            await SaveChangesAsync();
+        }
+
+        /// <summary>
+        /// 添加或更新实体
+        /// </summary>
+        /// <param name="key">更新键规则</param>
+        /// <param name="entities">需要保存的实体</param>
+        /// <returns>保存成功</returns>
+        public async Task AddOrUpdateSavedAsync<TKey>(Expression<Func<T, TKey>> key, IEnumerable<T> entities)
+        {
+            AddOrUpdate(key, entities);
+            await SaveChangesAsync();
+        }
+
         /// <summary>
         /// 添加实体并保存(异步)
         /// </summary>

+ 62 - 11
src/Masuit.MyBlogs.Core/Infrastructure/Services/Interface/IBaseService.cs

@@ -1,4 +1,4 @@
-using EFSecondLevelCache.Core;
+using Masuit.Tools.Models;
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -316,12 +316,11 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Services.Interface
         /// <typeparam name="TS"></typeparam>
         /// <param name="pageIndex">第几页</param>
         /// <param name="pageSize">每页大小</param>
-        /// <param name="totalCount">数据总数</param>
         /// <param name="where">where Lambda条件表达式</param>
         /// <param name="orderby">orderby Lambda条件表达式</param>
         /// <param name="isAsc">升序降序</param>
         /// <returns>还未执行的SQL语句</returns>
-        IQueryable<T> GetPages<TS>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> where, Expression<Func<T, TS>> orderby, bool isAsc);
+        PagedList<T> GetPages<TS>(int pageIndex, int pageSize, Expression<Func<T, bool>> where, Expression<Func<T, TS>> orderby, bool isAsc);
 
         /// <summary>
         /// 高效分页查询方法,取出被AutoMapper映射后的数据集合
@@ -330,12 +329,11 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Services.Interface
         /// <typeparam name="TDto"></typeparam>
         /// <param name="pageIndex">第几页</param>
         /// <param name="pageSize">每页大小</param>
-        /// <param name="totalCount">数据总数</param>
         /// <param name="where">where Lambda条件表达式</param>
         /// <param name="orderby">orderby Lambda条件表达式</param>
         /// <param name="isAsc">升序降序</param>
         /// <returns>还未执行的SQL语句</returns>
-        IQueryable<TDto> GetPages<TS, TDto>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> where, Expression<Func<T, TS>> orderby, bool isAsc) where TDto : class;
+        PagedList<TDto> GetPages<TS, TDto>(int pageIndex, int pageSize, Expression<Func<T, bool>> where, Expression<Func<T, TS>> orderby, bool isAsc) where TDto : class;
 
         /// <summary>
         /// 高效分页查询方法,优先从二级缓存读取
@@ -343,12 +341,11 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Services.Interface
         /// <typeparam name="TS"></typeparam>
         /// <param name="pageIndex">第几页</param>
         /// <param name="pageSize">每页大小</param>
-        /// <param name="totalCount">数据总数</param>
         /// <param name="where">where Lambda条件表达式</param>
         /// <param name="orderby">orderby Lambda条件表达式</param>
         /// <param name="isAsc">升序降序</param>
         /// <returns>还未执行的SQL语句</returns>
-        EFCachedQueryable<T> GetPagesFromCache<TS>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc);
+        PagedList<T> GetPagesFromCache<TS>(int pageIndex, int pageSize, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc);
 
         /// <summary>
         /// 高效分页查询方法,优先从二级缓存读取,取出被AutoMapper映射后的数据集合
@@ -357,12 +354,11 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Services.Interface
         /// <typeparam name="TDto"></typeparam>
         /// <param name="pageIndex">第几页</param>
         /// <param name="pageSize">每页大小</param>
-        /// <param name="totalCount">数据总数</param>
         /// <param name="where">where Lambda条件表达式</param>
         /// <param name="orderby">orderby Lambda条件表达式</param>
         /// <param name="isAsc">升序降序</param>
         /// <returns>还未执行的SQL语句</returns>
-        EFCachedQueryable<TDto> GetPagesFromCache<TS, TDto>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc) where TDto : class;
+        PagedList<TDto> GetPagesFromCache<TS, TDto>(int pageIndex, int pageSize, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc) where TDto : class;
 
         /// <summary>
         /// 高效分页查询方法(不跟踪实体)
@@ -370,12 +366,11 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Services.Interface
         /// <typeparam name="TS"></typeparam>
         /// <param name="pageIndex">第几页</param>
         /// <param name="pageSize">每页大小</param>
-        /// <param name="totalCount">数据总数</param>
         /// <param name="where">where Lambda条件表达式</param>
         /// <param name="orderby">orderby Lambda条件表达式</param>
         /// <param name="isAsc">升序降序</param>
         /// <returns>还未执行的SQL语句</returns>
-        IQueryable<T> GetPagesNoTracking<TS>(int pageIndex, int pageSize, out int totalCount, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
+        PagedList<T> GetPagesNoTracking<TS>(int pageIndex, int pageSize, Expression<Func<T, bool>> @where, Expression<Func<T, TS>> @orderby, bool isAsc = true);
 
         /// <summary>
         /// 根据ID删除实体
@@ -454,6 +449,30 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Services.Interface
         /// <returns>添加成功</returns>
         T AddEntity(T t);
 
+        /// <summary>
+        /// 添加或更新实体
+        /// </summary>
+        /// <param name="key">更新键规则</param>
+        /// <param name="t">需要保存的实体</param>
+        /// <returns>保存成功</returns>
+        T AddOrUpdate<TKey>(Expression<Func<T, TKey>> key, T t);
+
+        /// <summary>
+        /// 添加或更新实体
+        /// </summary>
+        /// <param name="key">更新键规则</param>
+        /// <param name="entities">需要保存的实体</param>
+        /// <returns>保存成功</returns>
+        void AddOrUpdate<TKey>(Expression<Func<T, TKey>> key, params T[] entities);
+
+        /// <summary>
+        /// 添加或更新实体
+        /// </summary>
+        /// <param name="key">更新键规则</param>
+        /// <param name="entities">需要保存的实体</param>
+        /// <returns>保存成功</returns>
+        void AddOrUpdate<TKey>(Expression<Func<T, TKey>> key, IEnumerable<T> entities);
+
         /// <summary>
         /// 添加实体并保存
         /// </summary>
@@ -461,6 +480,38 @@ namespace Masuit.MyBlogs.Core.Infrastructure.Services.Interface
         /// <returns>添加成功</returns>
         T AddEntitySaved(T t);
 
+        /// <summary>
+        /// 添加或更新实体
+        /// </summary>
+        /// <param name="key">更新键规则</param>
+        /// <param name="t">需要保存的实体</param>
+        /// <returns>保存成功</returns>
+        T AddOrUpdateSaved<TKey>(Expression<Func<T, TKey>> key, T t);
+
+        /// <summary>
+        /// 添加或更新实体
+        /// </summary>
+        /// <param name="key">更新键规则</param>
+        /// <param name="entities">需要保存的实体</param>
+        /// <returns>保存成功</returns>
+        void AddOrUpdateSaved<TKey>(Expression<Func<T, TKey>> key, params T[] entities);
+
+        /// <summary>
+        /// 添加或更新实体
+        /// </summary>
+        /// <param name="key">更新键规则</param>
+        /// <param name="t">需要保存的实体</param>
+        /// <returns>保存成功</returns>
+        Task AddOrUpdateSavedAsync<TKey>(Expression<Func<T, TKey>> key, T t);
+
+        /// <summary>
+        /// 添加或更新实体
+        /// </summary>
+        /// <param name="key">更新键规则</param>
+        /// <param name="entities">需要保存的实体</param>
+        /// <returns>保存成功</returns>
+        Task AddOrUpdateSavedAsync<TKey>(Expression<Func<T, TKey>> key, IEnumerable<T> entities);
+
         /// <summary>
         /// 添加实体并保存(异步)
         /// </summary>

+ 20 - 0
src/Masuit.MyBlogs.Core/Models/DTO/DonateDto.cs

@@ -0,0 +1,20 @@
+namespace Masuit.MyBlogs.Core.Models.DTO
+{
+    /// <summary>
+    /// 打赏表
+    /// </summary>
+    public class DonateDto : DonateDtoBase
+    {
+
+        /// <summary>
+        /// 打赏人邮箱
+        /// </summary>
+        public string Email { get; set; }
+
+        /// <summary>
+        /// 打赏人的QQ或微信
+        /// </summary>
+        public string QQorWechat { get; set; }
+
+    }
+}

+ 40 - 0
src/Masuit.MyBlogs.Core/Models/DTO/DonateDtoBase.cs

@@ -0,0 +1,40 @@
+using System;
+
+namespace Masuit.MyBlogs.Core.Models.DTO
+{
+    /// <summary>
+    /// 打赏表
+    /// </summary>
+    public class DonateDtoBase : BaseDto
+    {
+        /// <summary>
+        /// 打赏人
+        /// </summary>
+        public string NickName { get; set; }
+
+        /// <summary>
+        /// 打赏人的显式邮箱
+        /// </summary>
+        public string EmailDisplay { get; set; }
+
+        /// <summary>
+        /// 打赏人的显式QQ或微信
+        /// </summary>
+        public string QQorWechatDisplay { get; set; }
+
+        /// <summary>
+        /// 打赏金额
+        /// </summary>
+        public string Amount { get; set; }
+
+        /// <summary>
+        /// 打赏途径
+        /// </summary>
+        public string Via { get; set; }
+
+        /// <summary>
+        /// 打赏时间
+        /// </summary>
+        public DateTime DonateTime { get; set; }
+    }
+}

+ 3 - 1
src/Masuit.MyBlogs.Core/Models/Pagination.cs

@@ -4,15 +4,17 @@ namespace Masuit.MyBlogs.Core.Models
 {
     public class Pagination
     {
-        public Pagination(int page, int size, OrderBy? orderBy = null)
+        public Pagination(int page, int size, int total, OrderBy? orderBy = null)
         {
             Page = page;
             Size = size;
+            TotalCount = total;
             OrderBy = orderBy;
         }
 
         public int Page { get; set; } = 1;
         public int Size { get; set; } = 15;
         public OrderBy? OrderBy { get; set; }
+        public int TotalCount { get; set; }
     }
 }

+ 0 - 38
src/Masuit.MyBlogs.Core/Models/ViewModel/PageDataModel.cs

@@ -1,38 +0,0 @@
-using System;
-
-namespace Masuit.MyBlogs.Core.Models.ViewModel
-{
-    /// <summary>
-    /// 分页数据模型
-    /// </summary>
-    public class PageDataModel
-    {
-        /// <summary>
-        /// 分页数据模型
-        /// </summary>
-        /// <param name="data">数据</param>
-        /// <param name="pageCount">页数</param>
-        /// <param name="totalCount">总条数</param>
-        public PageDataModel(object data, int pageCount, int totalCount)
-        {
-            this.Data = data;
-            this.PageCount = pageCount;
-            this.TotalCount = totalCount;
-        }
-
-        /// <summary>
-        /// 分页数据
-        /// </summary>
-        public Object Data { get; set; }
-
-        /// <summary>
-        /// 总页数
-        /// </summary>
-        public int PageCount { get; set; }
-
-        /// <summary>
-        /// 总条数
-        /// </summary>
-        public int TotalCount { get; set; }
-    }
-}

+ 4 - 6
src/Masuit.MyBlogs.Core/Views/Post/History.cshtml

@@ -1,6 +1,6 @@
-@using Masuit.MyBlogs.Core.Models.DTO
+@using Masuit.MyBlogs.Core.Models
 @using Masuit.MyBlogs.Core.Models.Entity
-@model List<Masuit.MyBlogs.Core.Models.Entity.PostHistoryVersion>
+@model Masuit.Tools.Models.PagedList<Masuit.MyBlogs.Core.Models.Entity.PostHistoryVersion>
 @{
     var post = (Post)ViewBag.Primary;
     ViewBag.Title = post.Title + "的历史版本";
@@ -40,7 +40,7 @@
                 <td>@post.ModifyDate.ToString("yyyy-MM-dd HH:mm:ss")</td>
                 <td>@post.Modifier</td>
             </tr>
-            @foreach (var p in Model)
+            @foreach (var p in Model.Data)
             {
                 <tr>
                     <td style="text-align: center">
@@ -60,7 +60,7 @@
     </table>
     <div class="col-md-12 text-center">
         @{
-            await Html.RenderPartialAsync("_Pagination", ViewData["page"]);
+            await Html.RenderPartialAsync("_Pagination", new Pagination(Model.CurrentPage, Model.PageSize, Model.TotalCount));
         }
     </div>
     @if (ad != null)
@@ -78,8 +78,6 @@
 			}
 			if ($("input[name='vers']:checked").length >= 3) {
 				$("input[name='vers']:checked:eq(1)").prop('checked', false);
-           } else {
-                //$("input[name='vers']").prop('checked', false);
            }
 		});
         $("#compare").on("click", function(e) {

+ 1 - 2
src/Masuit.MyBlogs.Core/Views/Shared/_Pagination.cshtml

@@ -2,8 +2,7 @@
 @using Masuit.MyBlogs.Core.Common
 @using Masuit.Tools
 @{
-    int count = ViewBag.Total;
-    int pages = Math.Ceiling(count / (Model.Size > 0 ? Model.Size : 15.0)).ToInt32();
+    int pages = Math.Ceiling(Model.TotalCount / (Model.Size > 0 ? Model.Size : 15.0)).ToInt32();
     int current = Model.Page > 0 ? Model.Page : 1;
     int pageStart = current - 4 > 0 ? current - 4 : 1;
     int pageEnd = current + 4 >= pages ? pages : current + 4;