基于Thinkphp8框架自研博客系统
文章、案例、单页三块内容,配上采集、统计、SEO 和一套自研后台。这篇把这套博客系统从里到外拆开讲:前台有哪些能力、后台怎么维护内容、用了什么技术栈,以及几个实现上的取舍。
这套博客不是套的主题模板,是照着「我要怎么发内容」这件事一行行写出来的。没有多用户、没有评论区,把力气全放在三件事上:写得快、管得住、读得顺。
下面按「前台能干什么 → 后台怎么用 → 用了什么技术 → 为什么这么选」走一遍。
一、前台:读者看到的部分
1. 首页
首屏是一句站点定位,下面是「置顶推荐」——左边一张大图卡片,右边三条简讯。这个区不是写死的,后台可以切成自动(按置顶标记 + 排序值取前 4 条)或手动(指定文章 ID,顺序就是录入顺序)。
再往下是「最新文章」三列网格。右侧栏依次是:关于我、文章分类、最近更新、热门排行。侧栏的头像、昵称、一句话、QQ、邮箱,全在后台「内容 → 首页设置」里改,不用碰代码。
2. 文章
列表页带分类筛选、关键词搜索和分页。搜索不是简单地对标题做 like,而是标题、简介、正文三处都查,命中位置不同排序也不同——标题命中的排最前,避免搜一个词出来的第一条只是正文里提了一嘴。
详情页的正文支持四件事,这是最容易看出「是不是自己写的」的地方:
- 代码高亮:编辑器里插入代码块,前台由 Prism 上色,右上角有中文「复制」按钮;剪贴板接口不可用时自动降级到 execCommand,非 HTTPS 环境也能复制
- 图片点击放大:正文图统一走灯箱,不跳新页面
- 附件下载卡片:正文里放一个指向 .zip / .pdf 的链接,前台会自动识别扩展名渲染成下载卡片,不会出现一行光秃秃的超链接
- 视频自适应:video 标签和 B 站 / 腾讯视频的 iframe 都按容器宽度等比缩放,窄屏不溢出
3. 案例与单页
案例用来放项目复盘:封面、客户、周期、技术标签、多图图集,详情页是「左侧图文 + 右侧信息卡」的结构。单页是 /page/{slug} 的形式,关于我们、联系我们这类内容都属于它,不用新建控制器。
也就是说,文章、案例、单页三块内容各有自己的表和后台页面,但共用同一套服务层逻辑,只是前台呈现形态不同。
4. 顶栏与联系入口
顶栏 logo 读后台配置,导航来自「装修 → 导航管理」,支持二级菜单。导航的选中态是一条 2px 底线:默认隐藏,hover 淡入 45%,选中实色并加粗。判断逻辑对详情页也生效——打开 /article/19,「文章」照样点亮。
右上角「联系我」是弹窗,电话、微信号、二维码三块都能配。二维码留空时弹窗会自动收成单栏,不会留一块空白框。
5. 几个不显眼但影响体验的细节
- 顶部加载进度条:页面最顶端 3px,跟着资源加载往前走,带一道流动高光。这段脚本必须内联在 body 最前面——放到外层 JS 里没意义,那时页面基本已经 load 完了,进度条只能从 0 到 100 闪一下
- 图片懒加载 + 淡入:开关在后台,关掉就完全不出
loading="lazy";开启时图片进场做 0.55 秒淡入,缓存命中的图直接显示,不会闪一下 - 响应式:桌面 1440、平板 900、手机 390 三档都量过,导航在窄屏收成抽屉
二、后台:内容怎么维护
后台是 Layui 写的,左侧按「首页 / 内容 / 用户 / 装修 / 权限 / 设置 / 系统」分组。
1. 控制台
登录后第一屏就是数据:今日浏览、今日访客、文章总数、案例与单页数量,下面一张近 24 小时的 PV / UV 曲线(按小时聚合),右侧是内容排行和系统信息。不用点进统计模块,就知道今天有没有人来看。
2. 内容(七个模块)
| 模块 | 作用 |
|---|---|
| 首页设置 | 首屏文案、置顶来源与条数、文章每页条数、联系方式、侧栏关于我、顶部进度条开关与颜色 |
| 文章管理 | 增删改查、封面上传、置顶 / 推荐 / 显示三个开关、排序值 |
| 文章采集 | 填一个 URL,抓标题、封面、正文并入库,可选「直接发布」或「先预览」 |
| 分类管理 | 文章分类,前台筛选栏直接用 |
| 案例管理 | 项目复盘,含多图图集 |
| 单页管理 | 关于我们、联系我们这类独立页面,按 slug 访问 |
| 访问统计 | 逐条访问记录:时间、页面、IP、来源、浏览器、系统、设备、访客标识 |
3. 一条原则:跟展示有关的配置都放「内容」
这条是刻意的。「设置 → 系统设置」只放真正的系统级参数:后台标题、版权、ICP 备案、公安备案、统计代码、页脚站点名与简介、H5 端、电脑端 SEO 与 logo。
凡是「会影响前台长什么样」的开关和颜色,一律放「内容 → 首页设置」。好处很直接:改展示的人不用在系统设置里翻,也不会顺手改到影响运行的东西。
4. 上传与附件库
每个图片字段都是同一个组件:鼠标移上去出「图库选择 / 本地上传」两个入口。上传后进附件库,以后可以直接复用,不用重复传同一张图。
三、技术栈
| 层 | 选型 | 说明 |
|---|---|---|
| 框架 | ThinkPHP 8.1(多应用) | backend / frontend / api / common 四个应用,公共逻辑放 common |
| 运行时 | PHP 8.2 | 生产模式关闭调试,静态资源带版本号刷缓存 |
| 数据库 | MySQL 5.7 / InnoDB / utf8mb4 | 统一 zhongbo_ 前缀,图片存相对路径 |
| 后台 UI | Layui 2.13 | 表格、表单、弹层全是原生组件 |
| 前台 | 原生 CSS + 原生 JS | 没有框架、没有构建步骤,一个 blog.css、一个 blog.js |
| 富文本 | TinyMCE | 带 codesample,插代码块时选语言 |
| 代码高亮 | Prism.js | 按需打包 PHP / JS / HTML / CSS / SQL / Bash |
| 部署 | Nginx + 宝塔 | 站点根目录指向 public |
数据表(节选)
核心就这几张,没有为了「看起来专业」拆一堆关联表:
zhongbo_article # 文章:cid / title / image / intro / content
# browse / is_topping / is_recommend / is_show
zhongbo_article_category # 文章分类
zhongbo_case # 案例
zhongbo_page # 单页(按 slug 访问)
zhongbo_sys_config # 配置:type + key + value
zhongbo_visit_log # 访问日志,统计模块的数据源
zhongbo_dev_navigation # 导航,支持 pid 二级菜单
zhongbo_attach # 附件库
配置表用的是 type + key + value 的键值结构,而不是每个配置开一个字段。加一个开关只要加一条记录,不用改表结构——这次加「顶部进度条」就只动了两行 key。前台再把整包配置缓存成一份,读配置基本没有额外开销。
四、几个实现上的取舍
1. 前台为什么不用 Vue / React
博客的内容是服务端渲染的静态结构,交互只有搜索、弹窗、灯箱、翻页,上框架等于为一个开关拉一整个运行时。现在首屏 HTML 直出,没有 hydration,没有白屏等待,文本内容对搜索引擎也最友好。
2. 代码高亮为什么不在后端做
后端渲染要引一个 PHP 的语法高亮库,还得自己护一份语言白名单。交给 Prism 在浏览器按需加载,服务端只管把代码原样转义输出,简单,也不拖慢首屏。
3. 采集为什么自己写提取算法
没有引第三方正文提取库,核心是一个打分函数——段落总长乘以链接密度的补数,再乘上类名权重,取最高分的容器:
// 段落总长 ×(1 - 链接密度) × 类名权重,取最高分的容器作为正文
$score = $textLength * (1 - $linkDensity) * $classWeight;
拿到最高分的容器之后,再按白名单重建 HTML(p / h2~h4 / pre / code / img / ul / table 等),保证入库的正文干净,不会把脚本和广告一起带进来。
代码块还会做语言识别:language-*、brush:、highlight-source-*、figure.highlight php 这几种写法都认,html 归一成 markup、js 归一成 javascript,行号列直接丢掉。
五、现在它到什么程度
功能上是完整的:能写、能采、能统计、能做 SEO、手机端可用。日常流程就是——
- 看到好文章,丢进「文章采集」,选直接发布
- 自己写的,进「文章管理」新建,传封面,勾上显示
- 想让它上首页,勾「置顶」,排序值给大一点
- 要改文案、换颜色、调条数,都在「内容 → 首页设置」
接下来打算做的是文章标签、按标签聚合的归档页,还有把正文图片统一过一遍压缩。都不急,等真的需要再说。
写这套东西最大的收获其实不是功能本身,而是每改一个细节都得想清楚「它该待在哪一层」——是模板、是公共变量、还是配置表。想清楚这一点,后面加东西就快了。