template
blog
发布于 2026-04-13
技能:创建博客模块模板
概述
为博客模块化系统创建新的模块模板(header/footer/nav/section 等),包含 .njk 模板、.css 样式、.schema.json 配置定义三件套,并同步到数据库、创建实例、添加到页面。
项目背景
本项目是基于 Node.js + Nunjucks + MySQL 的博客系统,采用模块化页面组合架构。每个页面由多个模块按 sort_order 顺序渲染,模块类型包括 header、footer、nav、section 等。
模板文件结构
src/templates/
{type}/ # 模块类型目录:header, footer, nav, section
{slug}.njk # Nunjucks 模板(HTML结构)
{slug}.css # 样式文件
{slug}.schema.json # 配置 JSON Schema(定义可配置项)
创建步骤
第一步:创建三件套文件
.schema.json 规范
- 顶层
type: "object",properties定义可配置字段 - 每个字段需要
type、title,可选default、description - 颜色字段用
"format": "color" - 数组字段(如导航链接)用
type: "array"+items - 必须有
required数组
示例:
{
"type": "object",
"properties": {
"title": { "type": "string", "title": "标题", "default": "默认值" },
"bgColor": { "type": "string", "format": "color", "title": "背景颜色", "default": "#ffffff" },
"links": {
"type": "array",
"title": "链接列表",
"items": {
"type": "object",
"properties": {
"name": { "type": "string", "title": "名称" },
"url": { "type": "string", "title": "地址" }
},
"required": ["name", "url"]
}
}
},
"required": ["title"]
}
.njk 模板规范
- 使用 Nunjucks 语法,变量来自 schema 定义的字段 + section 类型的动态数据
- 用
{{ varName }}输出变量,{% if %}条件渲染,{% for %}循环 - style 属性中可使用 CSS 变量:
style="--var: {{ configValue }}" - HTML 内容用
{{ content | safe }}输出
section 类型模板可使用的动态数据变量:
- 文章列表页:
articles(数组),categories(数组),pagination(对象),currentCategoryId - 文章详情页:
article(对象, 含 contentHtml),prev,next - 文章字段:
id,title,summary,created_at_fmt,category_id,category_name - 分页字段:
page,pageSize,total,totalPages
.css 样式规范
- 纯 CSS,不使用预处理器
- 用模块特有的类名前缀避免冲突(如
.aside-nav,.article-list-section) - 响应式用
@media (max-width: 768px)和@media (min-width: 769px) - 可使用 CSS 变量
var(--name, fallback) - 应该遵循pc端、移动端样式最佳实践,视觉审美
- 公共配置 移动端字体,字体大小,间距,间隔,整体风格
第二步:同步模板到数据库
TOKEN=$(curl -s -X POST http://localhost:3300/api/login \
-H 'Content-Type: application/json' \
-d '{"username":"admin","password":"admin123"}' | python3 -c 'import sys,json; print(json.load(sys.stdin)["data"]["token"])')
curl -X POST http://localhost:3300/api/module-templates/sync \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-d '{"dryRun":false}'
第三步:创建模块实例
curl -X POST http://localhost:3300/api/module-instances \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-d '{
"name": "实例名称",
"type_id": <type_id>,
"template_id": <template_id>,
"config_data": { ... schema 定义的配置值 ... }
}'
第四步:添加到页面
# site_category_id 指定该模块属于哪个站点分类的配置方案(可选,不传则为通用配置)
curl -X POST http://localhost:3300/api/pages/{pageId}/modules \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-d '{"module_instance_id": <instance_id>, "site_category_id": <category_id>}'
第五步:调整模块顺序
# site_category_id 指定操作哪个分类下的配置(不传则操作通用配置)
curl -X PUT http://localhost:3300/api/pages/{pageId}/modules \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-d '{"site_category_id": <category_id>, "modules":[{"module_instance_id":"<id1>"},{"module_instance_id":"<id2>"}]}'
模块类型标识符对照
| 标识符 | 名称 | 说明 |
|---|---|---|
| header | 页头 | 网站顶部区域 |
| nav | 导航 | 主导航菜单 |
| section | 内容区 | 页面主体内容 |
| footer | 页脚 | 网站底部区域 |
注意:type_id 使用雪花算法生成的 BIGINT,不是固定数字。创建实例时需先通过 GET /api/module-types 查询实际 ID。
关键文件
- 模板目录:
src/templates/{type}/{slug}.* - 模板加载器:
src/services/templateLoader.js(本地文件优先 + 数据库兜底) - 渲染中间件:
src/middleware/systemModules.js(按 sort_order 渲染所有模块,section 注入动态数据) - 布局模板:
src/views/layouts/base.njk(hasPageModules=true 时纯模块渲染,否则回退旧布局) - 同步 API:
src/routes/api/module-templates.js→POST /api/module-templates/sync
站点分类与多配置方案(v2.4.0)
同一页面可按站点分类拥有多套模块配置方案。site_category_id 在 page_module_configs 表上:
- 添加模块到页面时传
site_category_id指定归属哪个分类方案 - 批量更新模块顺序时传
site_category_id限定操作范围 - 前台渲染时只使用当前激活分类对应的配置
- 不传
site_category_id则为通用配置(NULL)
注意事项
- section 类型模板的 config_data 会与动态数据合并,config_data 中的同名字段会被动态数据覆盖
- 模板 CSS 会被收集到
<style>标签中内联输出,注意类名不要冲突 - 开发环境不缓存模板,修改文件后刷新即可看到效果
- 新增模块类型需要先在
module_types表中添加记录