6.0 KiB
6.0 KiB
主题(皮肤)开发指南
目录结构
themes/{name}/
├── theme.json # 主题清单(必填)
├── views/ # Blade 视图(激活后前置到全局视图路径)
│ ├── partials/ # head / header / sidebar / footer 等公共片段
│ ├── index.blade.php
│ ├── show.blade.php
│ ├── list.blade.php
│ └── ... # 缺省视图自动回退默认主题(resources/views/)
└── assets/ # CSS / JS / 图片(/themes/{name}/assets/... 访问)
theme.json
{
"title": "主题标题",
"version": "1.0.0",
"description": "主题描述",
"author": "作者",
"screenshot": "screenshot.png",
"inject_points": ["head", "header", "sidebar_top", "sidebar_bottom", "content_top", "content_bottom", "post_content_top", "post_content_bottom", "footer", "body_end"]
}
视图解析规则
- 激活主题的
views/目录被前置到全局视图路径 - 页面视图用
@include('partials.header')等按名字解析 → 主题有同名 partial 就用主题的,否则用默认主题的 - 页面视图同理:主题提供
index.blade.php则覆盖默认首页,否则用resources/views/index.blade.php
所以做一个新皮肤通常只需要:theme.json + assets/style.css + 覆盖 partials/(head/header/sidebar/footer)+ 需要特别定制的页面视图。
布局结构(约定)
默认主题(resources/views/)
@include('partials.head') {{-- <head> 含 SEO meta --}}
<body>
@include('partials.header') {{-- 站点头 --}}
<div class="container main-layout"> {{-- 两栏容器 --}}
<main class="content">...页面内容...</main>
@include('partials.sidebar') {{-- 侧边栏(自动获得共享数据) --}}
</div>
@include('partials.footer') {{-- 页脚(含备案号) --}}
</body></html>
sablog 主题(两栏经典风)
@include('partials.head')
<body>
@include('partials.header') {{-- 打开 <div id="outmain"> + header,自闭合 --}}
<div id="page"> {{-- 页面视图自己开闭 #page --}}
<div id="content">...内容...</div>
@include('partials.sidebar')
</div>{{-- #page --}}
@include('partials.footer') {{-- <div id="footer"> + 关闭 #outmain --}}
</body></html>
关键约定:header 打开的容器由页面视图自闭合,footer 只负责自己打开的内容。避免把 footer 渲染进 flex 容器导致错位(历史教训)。
页面视图清单(控制器会传的数据)
| 视图 | 控制器 | 变量 |
|---|---|---|
index |
HomeController | $posts(分页) |
show |
PostController | $post, $comments, $contentHtml |
list |
Category/Archive | $posts, $category? / $archiveTitle? |
archives |
ArchiveController | $archives |
tags |
TagController | $tags |
tag |
TagController | $tag, $posts |
search |
SearchController | $posts, $keyword |
links |
LinkController | $links |
comments |
CommentController | $comments |
login / register / profile |
AuthController | — |
membership.index / membership.mine |
会员插件 | $plans / $subscriptions |
payments.sandbox / payments.result |
支付插件 | $payment |
侧边栏共享数据(SidebarComposer 自动注入所有前台视图)
$categories、$recentPosts、$recentComments、$hotTags、$links、$blogStats、$siteName、$siteDescription、$siteIcp
主题辅助函数
{{ theme('asset', 'style.css') }} {{-- 主题资产 URL --}}
{{ theme('var', 'key', '默认值') }} {{-- 主题变量(后台可编辑) --}}
{{ theme('name') }} {{-- 当前主题名 --}}
资产
- 开发期:
GET /themes/{name}/assets/{path}流式返回(带缓存头) - 生产:
php artisan theme:publish复制到public/themes/,由 Web 服务器托管
内容注入点(广告 / 统计 / 临时链接)
主题视图内置 10 个注入点(Blade @stack),后台「主题注入」页管理:
| 注入点 | 位置 | 典型用途 |
|---|---|---|
theme:head |
</head> 前 |
统计代码、广告、验证 |
theme:header |
页头下方 | 顶部横幅/公告 |
theme:sidebar_top |
侧边栏顶部 | 首屏广告 |
theme:sidebar_bottom |
侧边栏底部 | 广告/临时链接 |
theme:content_top |
内容区顶部 | 列表/文章上方横幅 |
theme:content_bottom |
内容区底部 | 分页后广告 |
theme:post_content_top |
文章正文前 | 正文顶部广告 |
theme:post_content_bottom |
文章正文后 | 正文底部广告 |
theme:footer |
页脚前 | 版权上方声明 |
theme:body_end |
</body> 前 |
统计代码 |
特性:
- 同一位置可添加多条注入块(名称 + HTML + 排序 + 启停),按排序渲染
- 插件可通过 filter
theme.inject.{point}追加 - 主题变量(stylevar 复活):后台「主题注入」→「主题变量」Tab,视图用
{{ theme('var', 'key') }}引用任意 HTML
新主题须在对应 partial/视图放置 @stack('theme:xxx') 才能接收注入。
声明注入点:theme.json 的 inject_points 声明主题实现了哪些注入点(缺省视为全部支持),后台主题卡片会展示,切换主题时一目了然。
多注入排序:同一位置可添加多条,后台「主题注入」页按列表拖拽排序,保存后按顺序渲染。
预览图
theme.json 的 screenshot 指向 assets/ 下的预览图(如 screenshot.png),后台主题管理以卡片形式展示。可用无头浏览器截图生成:node + playwright 打开站点首页保存为 themes/{name}/assets/screenshot.png。
移动端适配
主题 CSS 需自带 @media (max-width: 768px) 断点:容器改全宽、两栏改单栏、导航换行。内置 sablog / modern 已实现,新主题请参照。
打包与安装
- 目录打成 ZIP(根目录含 theme.json),后台「主题管理」上传安装,或远程市场安装
- 不能删除当前激活的主题