Captures the current working tree after theme slots, ArticleAccess, and the payment / paid-content plugins so subsequent work has a reviewable git history.
4.5 KiB
皮肤(主题)开发指南
目录格式
themes/{slug}/
theme.json # 元数据
assets/ # 静态资源(CSS/图片/预览)
style.css
preview.svg # 后台卡片预览(建议 16:10)
views/ # Blade,命名空间 theme::
layout.blade.php
home.blade.php
article.blade.php
...
theme.json 示例
{
"name": "my-theme",
"title": "我的皮肤",
"version": "1.0.0",
"description": "说明文字",
"slots": "*"
}
必须声明 slots
皮肤应在 theme.json 声明支持的注入槽(后台「皮肤」卡片会校验):
| 写法 | 含义 |
|---|---|
"slots": "*" 或 "all" |
支持全部标准槽(推荐) |
"slots": ["head", "sidebar", "my_slot"] |
显式列表;可混用 "*" 再加自定义槽 |
省略 slots |
不合规:后台标「未声明」;启用时警告 |
校验还会扫 views/**/*.blade.php 里的 @themeslot / ThemeSlot::render(非 default 主题会把未覆盖的 default 视图算进有效槽)。声明了但视图未调用 →「声明与视图不一致」。
视图约定
- 使用
@extends('theme::layout') - 控制器传:
$articles/$article/$categories/$settings/$seo - 静态资源 URL:
app(ThemeManager::class)->assetUrl('style.css')→/themes/{slug}/style.css - 文案:
__('frontend.nav.home')等,勿写死中英文
内容注入点(ThemeSlot)
主题应在固定位置调用 @themeslot('槽名')(或 ThemeSlot::render('槽名'))。
插件与后台「注入 / 广告 / 统计」都会写入同一套槽。
同一位置可多条
Hook::gather('theme.{slot}') 会按注册顺序把后台片段 + 各插件拼成一段 HTML。
同一槽塞 3 个插件广告 + 后台一段,都会出来(纵向叠放,由主题 CSS 决定外观)。
可控边界(换别人做的 theme)
| 可控 | 不可强控 |
|---|---|
标准槽名(API):head / sidebar / … |
像素级宽高、是否做成卡片 |
主题是否调用了 @themeslot(合规皮肤应全挂) |
侧栏在左还是右、主栏实际像素 |
建议尺寸写在 ThemeSlot::catalog() / 后台 helper |
第三方主题漏掉某个槽 → 该注入静默不显示 |
结论:槽名是硬约定,版式是软建议。别人做 theme 只要挂齐标准槽,内容就能到「大概那个位置」;精确到「300×250 居中」做不到,也不该做进核心。合规检查可后续做:扫描 views 是否包含全部标准 @themeslot。
尺寸/位置说明见 ThemeSlot::catalog()(后台「注入」Tab 的 helper 同步显示)。
| 槽名 | 典型用途 | 建议尺寸(软) |
|---|---|---|
head |
统计 / 额外 CSS·JS | 无版面 |
body_start / body_end |
body 首尾脚本 | 无版面 |
header_after |
页头横幅、公告 | 通栏高约 60–120px |
nav_after |
导航后临时入口 | 文字链 |
content_before / content_after |
主栏前后 | 主栏宽约 640–760px |
article_top / article_bottom |
文章广告 | 主栏宽 × 90–250px |
sidebar_before / sidebar / sidebar_after |
侧栏广告 / 临时链接 | 侧栏约 280–320px,多条叠放 |
footer_before / footer_after |
页脚附加 | 通栏 |
后台怎么填
/admin → 站点设置 → Tab「注入 / 广告 / 统计」:
- 统计代码 →
head - 侧栏广告 →
sidebar - 临时链接 HTML →
sidebar_after(可写<a href="...">活动</a>) - 文章顶/底广告 →
article_top/article_bottom
也可继续用 站点片段(Stylevars) 做纯文本侧栏块;友情链接仍走「友情链接」资源。
插件怎么注入
use App\Domain\Plugin\Hook;
use App\Domain\Theme\ThemeSlot;
Hook::listen(ThemeSlot::event(ThemeSlot::SIDEBAR), function (string $html): string {
return $html.'<p><a href="/promo">活动页</a></p>';
});
主题里任意位置
在任意 Blade 加一行即可,例如正文中间:
@themeslot('article_top')
{{-- 或自定义新槽:插件 listen theme.my_slot,主题写 @themeslot('my_slot') --}}
新槽无需改核心:约定 theme.{name} 事件即可。
发布
php artisan themes:publish
# 或后台「皮肤」→ 启用 / 发布静态资源
资源复制到 public/themes/{slug}/。
回退
ThemeManager 先注册 default views,再 prepend 当前主题;缺视图自动回退 default。
切换
后台「皮肤」卡片启用,或改 Settings general.active_theme。