本文由 FlintHub 开发文档归档发布。原始文档日期见标题前缀,来源:WWW/plugins/single_page/说明.md。
single_page 插件 — 单页/链接管理
在社区页脚展示站内静态页面与外部链接,支持后台管理。
一、功能概述
- 后台管理:侧边栏「单页/链接管理」入口,支持两种内容类型、排序、公开开关、编辑、删除。
- 站内页面(type=page):标题 + 正文(内置编辑器,可视化 / Markdown 双模式)+ URL Slug(如
about),前台通过/page/{slug}访问。 - 外部链接(type=link):标题 + 外部 URL(仅 http/https,前台自动加
rel="noopener"防劫持)。 - 页脚展示:读取全部公开记录,按排序权重升序渲染到页脚链接区(
footer_links钩子)。
二、目录结构
plugins/single_page/
├── plugin.json # 插件清单(hooks 注册)
├── Plugin.php # 生命周期(建表/卸载)+ 数据访问(getPublic/getBySlug/slugExists)
├── AdminController.php # 后台控制器(继承 BaseController,管理员鉴权)
├── FrontController.php # 前台控制器(/page/{slug} 渲染 + 404)
├── hook/
│ ├── init_after.php # 初始化后建表守卫(缓存标记,每请求 0 查询)
│ ├── route_register.php # 前台路由:GET /page/{slug}
│ ├── admin_route_register.php # 后台路由:列表/新增/编辑/删除
│ ├── admin_sidebar_links.php # 后台侧边栏入口
│ └── footer_links.php # 页脚链接区钩子输出
├── views/
│ ├── admin.php # 后台管理视图
│ └── page.php # 前台单页视图(干净布局)
├── lang/ (zh.php / en.php / zh_tw.php)
├── assets/
│ ├── style.css # 插件独立样式(零内联,不改核心 admin.css)
│ └── script.js # 类型切换 / 删除确认(外部 JS,零内联)
└── 说明.md三、数据存储
插件独立库:plugins/single_page/data/single_page.sqlite(\app\Helpers\Plugin::db('single_page') 自动建目录并写 .htaccess/web.config 防护)。
CREATE TABLE IF NOT EXISTS single_pages (
id INTEGER PRIMARY KEY,
type TEXT NOT NULL DEFAULT 'page', -- 'page' 站内页 | 'link' 外链
title TEXT NOT NULL,
content TEXT NOT NULL DEFAULT '', -- type=page 的正文
url TEXT NOT NULL DEFAULT '', -- type=link 的外部 URL
slug TEXT NOT NULL DEFAULT '', -- type=page 的 URL 别名,唯一
sort_order INTEGER NOT NULL DEFAULT 0, -- 页脚显示顺序
is_public INTEGER NOT NULL DEFAULT 1, -- 1=页脚显示且前台可访问
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL
);
CREATE UNIQUE INDEX IF NOT EXISTS idx_single_pages_slug ON single_pages(slug);建表由 Plugin::activate() + hook/init_after.php 双重保障,DDL 幂等(CREATE TABLE IF NOT EXISTS)。
四、路由
| 方法 | 路径 | 控制器动作 | 说明 |
|---|---|---|---|
| GET | /page/{slug} | FrontController::show | 站内单页渲染;不存在/未公开/非 page 类型一律 404 |
| GET | /admin/single-page | AdminController::index | 后台列表 + 添加/编辑表单 |
| POST | /admin/single-page/add | AdminController::add | 新增(CSRF 校验) |
| POST | /admin/single-page/edit | AdminController::edit | 编辑(CSRF 校验) |
| POST | /admin/single-page/delete | AdminController::delete | 删除(CSRF 校验) |
五、钩子
| 钩子 | 说明 |
|---|---|
init_after | 初始化后幂等建表 |
route_register | 注册前台单页路由 |
admin_route_register | 注册后台管理路由 |
admin_sidebar_links | 后台侧边栏「单页/链接管理」入口 |
footer_links | 页脚链接区输出(站内页 /page/{slug};外链 target="_blank" rel="noopener") |
页脚钩子复用核心布局 app/Views/layouts/main.php 中已存在的 footer_links 钩子位,无需修改核心代码。多个插件注册同一钩子时按插件激活顺序输出。
六、安全设计
- 后台权限:AdminController 继承
app\Controllers\Admin\BaseController,自动管理员鉴权 + 二次密码验证。 - 外链协议白名单:仅
http:///https://(preg_match('#^https?://#i', ...)),入库与页脚输出双重校验。 - 外链防劫持:页脚与后台预览统一
rel="noopener"。 - XSS 防护:后台视图全部
$this->e();页脚钩子内htmlspecialchars(ENT_QUOTES, 'UTF-8');正文由内置编辑器以 base64 存储,后台回显经decodeContent()解码,前台渲染走Content::formatPostContent()(纯文本转义 + 自动链接 + nl2br / HTML 白名单净化)。 - slug 白名单:
/^[a-z0-9-]{1,64}$/,防路径穿越与 URL 注入;唯一性冲突在后台提示。 - CSRF:所有写操作
Csrf::verifyOrDie()+ 表单隐藏域。 - SQL 注入:全部 PDO 预处理参数绑定。
- 未公开保护:
is_public=0的页面前台一律 404,不泄露存在性。
七、样式规范
- 零内联:视图内不写
<style>块、style=""属性和内联onclick等;所有样式收敛在assets/style.css,JS 逻辑收敛在assets/script.js。 - 不动核心 admin.css:后台页面完全复用核心通用类(
.admin-container/.admin-content/.admin-table/.btn/.form-input),插件专属样式(表单宽度、徽标、状态色等)增量写在插件自己的样式表里。
八、多语言
lang/zh.php、lang/en.php、lang/zh_tw.php 三语种同步,键前缀 plugin.single_page.*,核心 I18n 自动合并加载。