前言
先说一下我对 StarBlog 这个系列的文章的规划吧,在 StarBlog 的 1.x 版本,我会同步更新两个系列的文章
- 博客前台+接口开发笔记 (即当前已发布的这一系列文章)
- 博客Vue后台开发笔记 (后续开始持续发布)
最近很久没有更新 StarBlog 系列的文章,事实上我之前已经把【博客Vue后台开发笔记】基本完成了,但我想把 StarBlog 1.x版本的功能完善之后,把【前台+接口开发笔记】这系列完成之后,再开始更新【vue后台开发笔记】
所以最近一段时间对本项目的后端、前端代码做了很多修改,包括性能优化、UI调整、功能完善等,本文做一个简单的记录。(当然优化和改进是无止境的,欢迎各位同学提交 issues 和 pr!)
前台UI调整
本次更新我对前台和后台的UI都做了一些调整,对用户来说,UI调整是感知程度最强的,所以放在第一个介绍。
文章列表
文章列表界面的调整包括右上角的文章排序选项和重新设计的文章列表。
旧的文章列表直接使用 Bootstrap4 样式的 Card,card-header
里放置文章的分类名称,然后 card-body
里是文章标题和梗概,丑是丑了点,但更主要的问题是没有文章发布时间等额外信息,查看起来不太直观。旧版UI如下图:
新的文章列表如图,右上角增加了文章排序,可以根据标题、发表时间、更新时间进行正序/倒序的排序。
文章列表里的元素也做了重新设计,加入了封面图、发表时间、阅读量等信息元素,细节方面,每个文章卡片我加入了一点点阴影效果,文章梗概的文字使用了小号字体与 text-muted
样式,更好地与标题区分开来。
导航栏
在前面的文章列表UI里,可以看到顶部的导航栏也换了,这个修改没法说比旧版更好,只能说为了自适应移动设备做出了一些妥协。原本的导航栏还有图标,有更丰富的视觉效果,但是对移动端的兼容比较有限,各个导航菜单没法隐藏到侧边栏里,会平铺占用大量空间;新版的就是普通的Bootstrap风格导航栏,平平无奇,但可以自适应得比较好。
自适应模式下的旧版导航栏
自适应模式下的新版导航栏
后台UI调整
管理后台是审美的重灾区
目前使用的这套管理后台,是基于我之前的一个 SpringCloud 项目的管理后台修改而来
因为历史问题,有一些比较奇怪和难看的样式,在这次更新中,我一并修改了
相比之前,现在的后台UI顺眼多了😃
原本是这样的
现在是这样的
单纯看主界面还不是很明显
这次主要调整了背景颜色和简化各个界面的布局,可以看到导航栏也精简了很多按钮,只剩下一个用户按钮了。
全新的文章编辑界面
本次我重新设计了文章编辑界面
顶部增加了 breadcrumb
如果处在编辑模式,标题右侧模仿博客园的设计,新增了文章的链接,可以点击直接跳转到文章页面
底部是文章信息与各种设置
新增的 slug 功能可以缩短文章的链接地址,这个功能比较小,所以之前没有单独写一篇文章介绍。设置了 slug 之后,可以通过 starblog.com/p/slug
来访问文章。
下方的文章选项,可以设置文章的发表状态、标记、简介等,没什么特别需要介绍的。
文章分类支持多层级选择
文章管理
先看旧版的,难看的背景,莫名其妙的边距,总结就是难看
新版界面,页面干净很多,然后文章的筛选功能也增强了,现在除了搜索和分类筛选,还可以根据发表状态、文章标记来筛选文章。
其他页面也一样,是类似的修改思路,我就不一一贴图片和介绍了。
上传文章
原本整个UI都在左边,各个控件的宽度也没有一致,现在都改成居中了,控件样式也做了统一。
这里的文章分类选择同样支持多层级结构选择。
动画
大部分页面之前都没有什么动画,加载数据的时候是空白的,加载完成就直接呈现了,很生硬。
现在我给它们都加入了加载动画,感觉舒服多了;还有一个是UI细节继续调整。
这些动画体现在一切需要网络交互的界面上,比如文章列表、保存文章、上传文章这些界面,实现也很简单,ElementUI的大部分组件都可以通过添加 loading
属性来实现加载动画。
性能优化
性能瓶颈大部分在数据库IO上,还有一些是在内存管理方面,主要是和博客提供的图片功能有关。
分页
数据库这块的优化感知最强的是修改分页的实现,之前我是直接使用了 X.PagedList
组件来实现分页,但之前的写法有点问题,先把全部数据加载出来之后再分页,数据量大的时候性能就非常差了,现在全部改成了数据库分页。
目前使用的 ORM 是 FreeSQL ,可以通过 ISelect.Page
方法实现分页,生成出来的 SQL 应该是带类似 offset
和 limit
的,这是在数据库层面实现的分页,比读取全部数据再分页的性能会好很多。
X.PagedList
这个组件依然可以继续使用,只不过只用它的元数据就行,一个典型的代码块如下
IPagedList<Post> pagedList = new StaticPagedList<Post>(
await querySet.Page(param.Page, param.PageSize).Include(a => a.Category).ToListAsync(),
param.Page, param.PageSize, Convert.ToInt32(await querySet.CountAsync())
);
使用的时候分别读取其中的数据和分页元数据
return new ApiResponsePaged<Post> {
Message = "Get posts list",
Data = pagedList.ToList(),
Pagination = pagedList.ToPaginationMetadata()
};
修改的代码量不大,迁移成本很小。
图片库
本项目提供了随机图片接口,经过实测这个功能会占用比较多的内存,这可能是和这个功能的设计有关,因为需要根据传入的参数来调整、裁剪图片到合适的尺寸再返回,这个过程是在内存中实现的。
我看到 ImageSharp
的中间件里提供了一种思路,通过在本地缓存图片,以后再遇到相同参数的图片时就直接从文件系统读取返回,这可以节省一些内存,不过又带来了新的问题,会占用一些磁盘空间,特别是图片库很大的情况下,所以我目前还没有用这种思路来改造这个功能。
业务逻辑
- 保存和添加文章时检查slug是否可用
// 新建时
if (!string.IsNullOrWhiteSpace(dto.Slug) && !await _postService.CheckSlugAvailable(dto.Slug)) {
return ApiResponse.BadRequest("指定的 slug 已经被其他文章使用!");
}
// 更新时
if (!string.IsNullOrWhiteSpace(dto.Slug)) {
if (dto.Slug!= post.Slug && !await _postService.CheckSlugAvailable(dto.Slug)) {
return ApiResponse.BadRequest("指定的 slug 已经被其他文章使用!");
}
}
- 文章列表接口终于完善了,可以根据是否管理员来筛选不同状态的文章。(评论列表同样)
// 已登录则设置为管理员模式
// todo 后续改成根据角色确定管理员
var adminMode = User.Identity?.IsAuthenticated ?? false;
var pagedList = await _postService.GetPagedList(param, adminMode);
- 修改文章的时候可以同时修改文章标记和草稿状态,这个太简单就不附上代码了
bugfix
这没啥好说的,详见 github commits
不知不觉竟然已经有了 475 个 commits 了!真是太勤奋了
小结
OK,就是这些啦,这估计也是2023年 StarBlog 项目的最后一次功能更新,接着我会继续更新文章,争取在今年里把【博客前台+接口开发笔记】系列完结掉!~~(然后我就可以来做新项目了)~
在这里给大家拜个早年!敬请期待后续的新项目😃